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

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


The following commit(s) were added to refs/heads/branch-4.0 by this push:
     new 3fcfd66bc65 branch-4.0: [Fix](geo) fix memory leak in geo #58004 
(#58365)
3fcfd66bc65 is described below

commit 3fcfd66bc6589c89aeb75a3c238d434ca5602381
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Wed Nov 26 09:22:17 2025 +0800

    branch-4.0: [Fix](geo) fix memory leak in geo #58004 (#58365)
    
    Cherry-picked from #58004
    
    Co-authored-by: linrrarity <[email protected]>
---
 be/src/geo/geo_types.cpp                   |  20 +-
 be/src/geo/geo_types.h                     |  10 +-
 be/src/geo/wkb_parse.cpp                   |  92 +++---
 be/src/geo/wkb_parse.h                     |  22 +-
 be/src/geo/wkb_parse_ctx.h                 |  12 +-
 be/src/geo/wkt_lex.l                       |  21 +-
 be/src/geo/wkt_parse.cpp                   |  40 ++-
 be/src/geo/wkt_parse.h                     |   9 +-
 be/src/geo/wkt_parse_ctx.h                 |   9 +-
 be/src/geo/wkt_parse_type.h                |  20 +-
 be/src/geo/wkt_yacc.y                      | 175 ++++++-----
 be/src/vec/functions/functions_geo.cpp     |   4 +-
 be/test/geo/geo_types_test.cpp             | 459 +++++++++++++----------------
 be/test/geo/wkb_parse_test.cpp             | 179 +++++++++++
 be/test/geo/wkt_parse_test.cpp             |  10 +-
 be/test/vec/function/function_geo_test.cpp |  14 +-
 16 files changed, 642 insertions(+), 454 deletions(-)

diff --git a/be/src/geo/geo_types.cpp b/be/src/geo/geo_types.cpp
index 22c48fedc76..6c6f612ca1b 100644
--- a/be/src/geo/geo_types.cpp
+++ b/be/src/geo/geo_types.cpp
@@ -403,13 +403,15 @@ void GeoShape::encode_to(std::string* buf) {
     encode(buf);
 }
 
-GeoShape* GeoShape::from_wkt(const char* data, size_t size, GeoParseStatus* 
status) {
-    GeoShape* shape = nullptr;
-    *status = WktParse::parse_wkt(data, size, &shape);
+std::unique_ptr<GeoShape> GeoShape::from_wkt(const char* data, size_t size,
+                                             GeoParseStatus& status) {
+    std::unique_ptr<GeoShape> shape;
+    status = WktParse::parse_wkt(data, size, shape);
     return shape;
 }
 
-GeoShape* GeoShape::from_wkb(const char* data, size_t size, GeoParseStatus* 
status) {
+std::unique_ptr<GeoShape> GeoShape::from_wkb(const char* data, size_t size,
+                                             GeoParseStatus& status) {
     std::stringstream wkb;
 
     for (int i = 0; i < size; ++i) {
@@ -419,8 +421,8 @@ GeoShape* GeoShape::from_wkb(const char* data, size_t size, 
GeoParseStatus* stat
         wkb << *data;
         data++;
     }
-    GeoShape* shape = nullptr;
-    *status = WkbParse::parse_wkb(wkb, &shape);
+    std::unique_ptr<GeoShape> shape;
+    status = WkbParse::parse_wkb(wkb, shape);
     return shape;
 }
 
@@ -490,7 +492,7 @@ GeoCoordinateList GeoLine::to_coords() const {
     return coords;
 }
 
-const std::unique_ptr<GeoCoordinateListList> GeoPolygon::to_coords() const {
+std::unique_ptr<GeoCoordinateListList> GeoPolygon::to_coords() const {
     std::unique_ptr<GeoCoordinateListList> coordss(new 
GeoCoordinateListList());
     for (int i = 0; i < GeoPolygon::numLoops(); ++i) {
         std::unique_ptr<GeoCoordinateList> coords(new GeoCoordinateList());
@@ -510,12 +512,12 @@ const std::unique_ptr<GeoCoordinateListList> 
GeoPolygon::to_coords() const {
                 coords->add(coord);
             }
         }
-        coordss->add(coords.release());
+        coordss->add(std::move(coords));
     }
     return coordss;
 }
 
-const std::vector<std::unique_ptr<GeoCoordinateListList>> 
GeoMultiPolygon::to_coords() const {
+std::vector<std::unique_ptr<GeoCoordinateListList>> 
GeoMultiPolygon::to_coords() const {
     std::vector<std::unique_ptr<GeoCoordinateListList>> coordss;
     for (const auto& polygon : _polygons) {
         std::unique_ptr<GeoCoordinateListList> coords = polygon->to_coords();
diff --git a/be/src/geo/geo_types.h b/be/src/geo/geo_types.h
index dbc7901f1b3..9b2543b5227 100644
--- a/be/src/geo/geo_types.h
+++ b/be/src/geo/geo_types.h
@@ -51,9 +51,11 @@ public:
     // try to construct a GeoShape from a WKT. If construct successfully, a 
GeoShape will
     // be returned, and the client should delete it when don't need it.
     // return nullptr if convert failed, and reason will be set in status
-    static GeoShape* from_wkt(const char* data, size_t size, GeoParseStatus* 
status);
+    static std::unique_ptr<GeoShape> from_wkt(const char* data, size_t size,
+                                              GeoParseStatus& status);
 
-    static GeoShape* from_wkb(const char* data, size_t size, GeoParseStatus* 
status);
+    static std::unique_ptr<GeoShape> from_wkb(const char* data, size_t size,
+                                              GeoParseStatus& status);
 
     void encode_to(std::string* buf);
     bool decode_from(const void* data, size_t size);
@@ -160,7 +162,7 @@ public:
     ~GeoPolygon() override;
 
     GeoParseStatus from_coords(const GeoCoordinateListList& list);
-    const std::unique_ptr<GeoCoordinateListList> to_coords() const;
+    std::unique_ptr<GeoCoordinateListList> to_coords() const;
 
     GeoShapeType type() const override { return GEO_SHAPE_POLYGON; }
     const S2Polygon* polygon() const { return _polygon.get(); }
@@ -196,7 +198,7 @@ public:
 
     GeoParseStatus check_self_intersection();
     GeoParseStatus from_coords(const std::vector<GeoCoordinateListList>& list);
-    const std::vector<std::unique_ptr<GeoCoordinateListList>> to_coords() 
const;
+    std::vector<std::unique_ptr<GeoCoordinateListList>> to_coords() const;
 
     GeoShapeType type() const override { return GEO_SHAPE_MULTI_POLYGON; }
     const std::vector<std::unique_ptr<GeoPolygon>>& polygons() const { return 
_polygons; }
diff --git a/be/src/geo/wkb_parse.cpp b/be/src/geo/wkb_parse.cpp
index 7b345929fc0..b7d1c9b8ae8 100644
--- a/be/src/geo/wkb_parse.cpp
+++ b/be/src/geo/wkb_parse.cpp
@@ -20,6 +20,7 @@
 #include <cstddef>
 #include <istream>
 #include <sstream>
+#include <utility>
 #include <vector>
 
 #include "geo/ByteOrderDataInStream.h"
@@ -75,19 +76,17 @@ unsigned char ASCIIHexToUChar(char val) {
     }
 }
 
-GeoParseStatus WkbParse::parse_wkb(std::istream& is, GeoShape** shape) {
+GeoParseStatus WkbParse::parse_wkb(std::istream& is, 
std::unique_ptr<GeoShape>& shape) {
     WkbParseContext ctx;
 
-    ctx = *(WkbParse::read_hex(is, &ctx));
+    WkbParse::read_hex(is, ctx);
     if (ctx.parse_status == GEO_PARSE_OK) {
-        *shape = ctx.shape;
-    } else {
-        ctx.parse_status = GEO_PARSE_WKT_SYNTAX_ERROR;
+        shape = std::move(ctx.shape);
     }
     return ctx.parse_status;
 }
 
-WkbParseContext* WkbParse::read_hex(std::istream& is, WkbParseContext* ctx) {
+void WkbParse::read_hex(std::istream& is, WkbParseContext& ctx) {
     // setup input/output stream
     std::stringstream os(std::ios_base::binary | std::ios_base::in | 
std::ios_base::out);
 
@@ -99,8 +98,8 @@ WkbParseContext* 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;
-            return ctx;
+            ctx.parse_status = GEO_PARSE_WKB_SYNTAX_ERROR;
+            return;
         }
 
         const char high = static_cast<char>(input_high);
@@ -109,35 +108,35 @@ WkbParseContext* WkbParse::read_hex(std::istream& is, 
WkbParseContext* ctx) {
         const unsigned char result_high = ASCIIHexToUChar(high);
         const unsigned char result_low = ASCIIHexToUChar(low);
 
-        const unsigned char value = static_cast<unsigned char>((result_high << 
4) + result_low);
+        const auto value = static_cast<unsigned char>((result_high << 4) + 
result_low);
 
         // write the value to the output stream
         os << value;
     }
-    return WkbParse::read(os, ctx);
+    WkbParse::read(os, ctx);
 }
 
-WkbParseContext* WkbParse::read(std::istream& is, WkbParseContext* ctx) {
+void WkbParse::read(std::istream& is, WkbParseContext& ctx) {
     is.seekg(0, std::ios::end);
     auto size = is.tellg();
     is.seekg(0, std::ios::beg);
 
     // Check if size is valid
     if (size <= 0) {
-        ctx->parse_status = GEO_PARSE_WKB_SYNTAX_ERROR;
-        return ctx;
+        ctx.parse_status = 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;
-        return ctx;
+        ctx.parse_status = 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;
-        return ctx;
+        ctx.parse_status = GEO_PARSE_WKB_SYNTAX_ERROR;
+        return;
     }
 
     // First read the byte order using machine endian
@@ -145,44 +144,43 @@ WkbParseContext* WkbParse::read(std::istream& is, 
WkbParseContext* ctx) {
 
     // Create ByteOrderDataInStream with the correct byte order
     if (byteOrder == byteOrder::wkbNDR) {
-        ctx->dis = ByteOrderDataInStream(buf.data(), buf.size());
-        ctx->dis.setOrder(ByteOrderValues::ENDIAN_LITTLE);
+        ctx.dis = ByteOrderDataInStream(buf.data(), buf.size());
+        ctx.dis.setOrder(ByteOrderValues::ENDIAN_LITTLE);
     } else if (byteOrder == byteOrder::wkbXDR) {
-        ctx->dis = ByteOrderDataInStream(buf.data(), buf.size());
-        ctx->dis.setOrder(ByteOrderValues::ENDIAN_BIG);
+        ctx.dis = ByteOrderDataInStream(buf.data(), buf.size());
+        ctx.dis.setOrder(ByteOrderValues::ENDIAN_BIG);
     } else {
-        ctx->parse_status = GEO_PARSE_WKB_SYNTAX_ERROR;
-        return ctx;
+        ctx.parse_status = GEO_PARSE_WKB_SYNTAX_ERROR;
+        return;
     }
 
     std::unique_ptr<GeoShape> shape = readGeometry(ctx);
     if (!shape) {
-        ctx->parse_status = GEO_PARSE_WKB_SYNTAX_ERROR;
-        return ctx;
+        ctx.parse_status = GEO_PARSE_WKB_SYNTAX_ERROR;
+        return;
     }
 
-    ctx->shape = shape.release();
-    return ctx;
+    ctx.shape = std::move(shape);
 }
 
-std::unique_ptr<GeoShape> WkbParse::readGeometry(WkbParseContext* ctx) {
+std::unique_ptr<GeoShape> WkbParse::readGeometry(WkbParseContext& ctx) {
     try {
         // Ensure we have enough data to read
-        if (ctx->dis.size() < 5) { // At least 1 byte for order and 4 bytes 
for type
+        if (ctx.dis.size() < 5) { // At least 1 byte for order and 4 bytes for 
type
             return nullptr;
         }
 
         // Skip the byte order as we've already handled it
-        ctx->dis.readByte();
+        ctx.dis.readByte();
 
-        uint32_t typeInt = ctx->dis.readUnsigned();
+        uint32_t typeInt = ctx.dis.readUnsigned();
 
         // Check if geometry has SRID
         bool has_srid = (typeInt & WKB_SRID_FLAG) != 0;
 
         // Read SRID if present
         if (has_srid) {
-            ctx->dis.readUnsigned(); // Read and store SRID if needed
+            ctx.dis.readUnsigned(); // Read and store SRID if needed
         }
 
         // Get the base geometry type
@@ -211,7 +209,7 @@ std::unique_ptr<GeoShape> 
WkbParse::readGeometry(WkbParseContext* ctx) {
     }
 }
 
-std::unique_ptr<GeoPoint> WkbParse::readPoint(WkbParseContext* ctx) {
+std::unique_ptr<GeoPoint> WkbParse::readPoint(WkbParseContext& ctx) {
     GeoCoordinateList coords = WkbParse::readCoordinateList(1, ctx);
     if (coords.list.empty()) {
         return nullptr;
@@ -225,8 +223,8 @@ std::unique_ptr<GeoPoint> 
WkbParse::readPoint(WkbParseContext* ctx) {
     return point;
 }
 
-std::unique_ptr<GeoLine> WkbParse::readLine(WkbParseContext* ctx) {
-    uint32_t size = ctx->dis.readUnsigned();
+std::unique_ptr<GeoLine> WkbParse::readLine(WkbParseContext& ctx) {
+    uint32_t size = ctx.dis.readUnsigned();
     if (minMemSize(wkbLine, size, ctx) != GEO_PARSE_OK) {
         return nullptr;
     }
@@ -244,15 +242,15 @@ std::unique_ptr<GeoLine> 
WkbParse::readLine(WkbParseContext* ctx) {
     return line;
 }
 
-std::unique_ptr<GeoPolygon> WkbParse::readPolygon(WkbParseContext* ctx) {
-    uint32_t num_loops = ctx->dis.readUnsigned();
+std::unique_ptr<GeoPolygon> WkbParse::readPolygon(WkbParseContext& ctx) {
+    uint32_t num_loops = ctx.dis.readUnsigned();
     if (minMemSize(wkbPolygon, num_loops, ctx) != GEO_PARSE_OK) {
         return nullptr;
     }
 
     GeoCoordinateListList coordss;
     for (uint32_t i = 0; i < num_loops; ++i) {
-        uint32_t size = ctx->dis.readUnsigned();
+        uint32_t size = ctx.dis.readUnsigned();
         if (size < 3) { // A polygon loop must have at least 3 points
             return nullptr;
         }
@@ -262,7 +260,7 @@ std::unique_ptr<GeoPolygon> 
WkbParse::readPolygon(WkbParseContext* ctx) {
         if (coords->list.empty()) {
             return nullptr;
         }
-        coordss.add(coords.release());
+        coordss.add(std::move(coords));
     }
 
     std::unique_ptr<GeoPolygon> polygon = GeoPolygon::create_unique();
@@ -273,7 +271,7 @@ std::unique_ptr<GeoPolygon> 
WkbParse::readPolygon(WkbParseContext* ctx) {
     return polygon;
 }
 
-GeoCoordinateList WkbParse::readCoordinateList(unsigned size, WkbParseContext* 
ctx) {
+GeoCoordinateList WkbParse::readCoordinateList(unsigned size, WkbParseContext& 
ctx) {
     GeoCoordinateList coords;
     for (uint32_t i = 0; i < size; i++) {
         if (!readCoordinate(ctx)) {
@@ -281,14 +279,14 @@ GeoCoordinateList WkbParse::readCoordinateList(unsigned 
size, WkbParseContext* c
         }
         unsigned int j = 0;
         GeoCoordinate coord;
-        coord.x = ctx->ordValues[j++];
-        coord.y = ctx->ordValues[j++];
+        coord.x = ctx.ordValues[j++];
+        coord.y = ctx.ordValues[j++];
         coords.add(coord);
     }
     return coords;
 }
 
-GeoParseStatus WkbParse::minMemSize(int wkbType, uint64_t size, 
WkbParseContext* ctx) {
+GeoParseStatus WkbParse::minMemSize(int wkbType, uint64_t size, 
WkbParseContext& ctx) {
     uint64_t minSize = 0;
     constexpr uint64_t minCoordSize = 2 * sizeof(double);
     //constexpr uint64_t minPtSize = (1+4) + minCoordSize;
@@ -305,14 +303,14 @@ GeoParseStatus WkbParse::minMemSize(int wkbType, uint64_t 
size, WkbParseContext*
         minSize = size * minLoopSize;
         break;
     }
-    if (ctx->dis.size() < minSize) {
+    if (ctx.dis.size() < minSize) {
         return GEO_PARSE_WKB_SYNTAX_ERROR;
     }
     return GEO_PARSE_OK;
 }
-bool WkbParse::readCoordinate(WkbParseContext* ctx) {
-    for (std::size_t i = 0; i < ctx->inputDimension; ++i) {
-        ctx->ordValues[i] = ctx->dis.readDouble();
+bool WkbParse::readCoordinate(WkbParseContext& ctx) {
+    for (std::size_t i = 0; i < ctx.inputDimension; ++i) {
+        ctx.ordValues[i] = ctx.dis.readDouble();
     }
 
     return true;
diff --git a/be/src/geo/wkb_parse.h b/be/src/geo/wkb_parse.h
index de6d0e9b2d9..856c9817ffb 100644
--- a/be/src/geo/wkb_parse.h
+++ b/be/src/geo/wkb_parse.h
@@ -46,26 +46,26 @@ constexpr uint32_t WKB_TYPE_MASK = 0xFF;
 
 class WkbParse {
 public:
-    static GeoParseStatus parse_wkb(std::istream& is, GeoShape** shape);
+    static GeoParseStatus parse_wkb(std::istream& is, 
std::unique_ptr<GeoShape>& shape);
 
-    static WkbParseContext* read_hex(std::istream& is, WkbParseContext* ctx);
+private:
+    static void read_hex(std::istream& is, WkbParseContext& ctx);
 
-    static WkbParseContext* read(std::istream& is, WkbParseContext* ctx);
+    static void read(std::istream& is, WkbParseContext& ctx);
 
-    static std::unique_ptr<GeoShape> readGeometry(WkbParseContext* ctx);
+    static std::unique_ptr<GeoShape> readGeometry(WkbParseContext& ctx);
 
-private:
-    static std::unique_ptr<GeoPoint> readPoint(WkbParseContext* ctx);
+    static std::unique_ptr<GeoPoint> readPoint(WkbParseContext& ctx);
 
-    static std::unique_ptr<GeoLine> readLine(WkbParseContext* ctx);
+    static std::unique_ptr<GeoLine> readLine(WkbParseContext& ctx);
 
-    static std::unique_ptr<GeoPolygon> readPolygon(WkbParseContext* ctx);
+    static std::unique_ptr<GeoPolygon> readPolygon(WkbParseContext& ctx);
 
-    static GeoCoordinateList readCoordinateList(unsigned size, 
WkbParseContext* ctx);
+    static GeoCoordinateList readCoordinateList(unsigned size, 
WkbParseContext& ctx);
 
-    static GeoParseStatus minMemSize(int wkbType, uint64_t size, 
WkbParseContext* ctx);
+    static GeoParseStatus minMemSize(int wkbType, uint64_t size, 
WkbParseContext& ctx);
 
-    static bool readCoordinate(WkbParseContext* ctx);
+    static bool readCoordinate(WkbParseContext& ctx);
 };
 
 } // namespace doris
diff --git a/be/src/geo/wkb_parse_ctx.h b/be/src/geo/wkb_parse_ctx.h
index eb47d7fc1ba..5c8bec43a71 100644
--- a/be/src/geo/wkb_parse_ctx.h
+++ b/be/src/geo/wkb_parse_ctx.h
@@ -17,12 +17,12 @@
 
 #pragma once
 
-#include "ByteOrderDataInStream.h"
-#include "array"
+#include <array>
+#include <memory>
 
-namespace doris {
-class GeoShape;
-}
+#include "ByteOrderDataInStream.h"
+#include "geo/geo_common.h"
+#include "geo/geo_types.h"
 
 struct WkbParseContext {
     unsigned int inputDimension = 2;
@@ -33,6 +33,6 @@ struct WkbParseContext {
 
     int srid;
 
-    doris::GeoShape* shape = nullptr;
+    std::unique_ptr<doris::GeoShape> shape = nullptr;
     doris::GeoParseStatus parse_status = doris::GEO_PARSE_OK;
 };
diff --git a/be/src/geo/wkt_lex.l b/be/src/geo/wkt_lex.l
index af27f5550c0..5e73238cc97 100644
--- a/be/src/geo/wkt_lex.l
+++ b/be/src/geo/wkt_lex.l
@@ -30,14 +30,14 @@ class GeoShape;
 #include "geo/wkt_parse_ctx.h"
 #include "geo/wkt_parse_type.h"
 #include "geo/wkt_yacc.y.hpp"
-
-#define YYSTYPE WKT_STYPE
 #define YY_EXTRA_TYPE  WktParseContext*
 
+#undef YY_DECL
+#define YY_DECL wkt_::parser::symbol_type wkt_lex(WktParseContext* ctx, 
yyscan_t yyscanner)
+
 %}
 
 %option case-insensitive
-%option bison-bridge
 %option reentrant
 %option never-interactive
 %option prefix="wkt_"
@@ -48,17 +48,16 @@ class GeoShape;
 %%
 
 -?(([0-9]+\.?)|([0-9]*\.?[0-9]+)([eE][-+]?[0-9]+)?) {
-    yylval->double_value = atof(yytext);
-    return NUMERIC;
+    return wkt_::parser::make_NUMERIC(atof(yytext));
 }
 
-MULTIPOLYGON { return KW_MULTI_POLYGON; }
-MULTILINESTRING { return KW_MULTI_LINESTRING; }
-MULTIPOINT { return KW_MULTI_POINT; }
-POLYGON { return KW_POLYGON; }
-LINESTRING { return KW_LINESTRING; }
+MULTIPOLYGON { return wkt_::parser::make_KW_MULTI_POLYGON(); }
+MULTILINESTRING { return wkt_::parser::make_KW_MULTI_LINESTRING(); }
+MULTIPOINT { return wkt_::parser::make_KW_MULTI_POINT(); }
+POLYGON { return wkt_::parser::make_KW_POLYGON(); }
+LINESTRING { return wkt_::parser::make_KW_LINESTRING(); }
 POINT { 
-    return KW_POINT; }
+    return wkt_::parser::make_KW_POINT(); }
 
 \( |
 \) |
diff --git a/be/src/geo/wkt_parse.cpp b/be/src/geo/wkt_parse.cpp
index 9f48f268fbc..3435fb985f7 100644
--- a/be/src/geo/wkt_parse.cpp
+++ b/be/src/geo/wkt_parse.cpp
@@ -17,35 +17,43 @@
 
 #include "geo/wkt_parse.h"
 
+#include <utility>
+
+#include "geo/wkt_lex.l.h"
 #include "geo/wkt_parse_ctx.h"
 #include "geo/wkt_parse_type.h" // IWYU pragma: keep
 #include "geo/wkt_yacc.y.hpp"
 
-#define YYSTYPE WKT_STYPE
-#define YY_EXTRA_TYPE WktParseContext*
-#include "geo/wkt_lex.l.h"
+extern int wkt_lex_init_extra(WktParseContext*, yyscan_t*);
 
 namespace doris {
 #include "common/compile_check_avoid_begin.h"
 
-GeoParseStatus WktParse::parse_wkt(const char* str, size_t len, GeoShape** 
shape) {
+GeoParseStatus WktParse::parse_wkt(const char* str, size_t len, 
std::unique_ptr<GeoShape>& shape) {
     WktParseContext ctx;
-    // initialize lexer
-    wkt_lex_init_extra(&ctx, &ctx.scaninfo);
-    wkt__scan_bytes(str, len, ctx.scaninfo);
 
-    // parse
-    auto res = wkt_parse(&ctx);
-    wkt_lex_destroy(ctx.scaninfo);
-    if (res == 0) {
-        *shape = ctx.shape;
-    } else {
-        if (ctx.parse_status == GEO_PARSE_OK) {
-            ctx.parse_status = GEO_PARSE_WKT_SYNTAX_ERROR;
-        }
+    if (wkt_parse(str, len, ctx) == GEO_PARSE_OK) {
+        shape = std::move(ctx.shape);
+    } else if (ctx.parse_status == 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;
     }
     return ctx.parse_status;
 }
 
+int WktParse::wkt_parse(const char* str, size_t len, WktParseContext& ctx) {
+    wkt_lex_init_extra(&ctx, &ctx.scaninfo);
+    YY_BUFFER_STATE buffer = wkt__scan_bytes(str, len, ctx.scaninfo);
+
+    wkt_::parser parser(&ctx, ctx.scaninfo);
+    int res = parser.parse();
+    wkt__delete_buffer(buffer, ctx.scaninfo);
+    wkt_lex_destroy(ctx.scaninfo);
+    return res;
+}
+
 #include "common/compile_check_avoid_end.h"
 } // namespace doris
diff --git a/be/src/geo/wkt_parse.h b/be/src/geo/wkt_parse.h
index 9dfcca98dd2..c14cedf1905 100644
--- a/be/src/geo/wkt_parse.h
+++ b/be/src/geo/wkt_parse.h
@@ -17,9 +17,11 @@
 
 #pragma once
 
-#include <stddef.h>
+#include <cstddef>
+#include <memory>
 
 #include "geo/geo_common.h"
+#include "geo/wkt_parse_ctx.h"
 
 namespace doris {
 
@@ -30,7 +32,10 @@ public:
     // Parse WKT(Well Known Text) to a GeoShape.
     // Return a valid GeoShape if input WKT is supported.
     // Return null if WKT is not supported or invalid
-    static GeoParseStatus parse_wkt(const char* str, size_t len, GeoShape** 
shape);
+    static GeoParseStatus parse_wkt(const char* str, size_t len, 
std::unique_ptr<GeoShape>& shape);
+
+private:
+    static int wkt_parse(const char* str, size_t len, WktParseContext& ctx);
 };
 
 } // namespace doris
diff --git a/be/src/geo/wkt_parse_ctx.h b/be/src/geo/wkt_parse_ctx.h
index 0c0f77adeb9..449080842fb 100644
--- a/be/src/geo/wkt_parse_ctx.h
+++ b/be/src/geo/wkt_parse_ctx.h
@@ -17,15 +17,14 @@
 
 #pragma once
 
-#include "geo/geo_common.h"
+#include <memory>
 
-namespace doris {
-class GeoShape;
-}
+#include "geo/geo_common.h"
+#include "geo/geo_types.h"
 
 typedef void* yyscan_t;
 struct WktParseContext {
     yyscan_t scaninfo;
-    doris::GeoShape* shape = nullptr;
+    std::unique_ptr<doris::GeoShape> shape = nullptr;
     doris::GeoParseStatus parse_status = doris::GEO_PARSE_OK;
 };
diff --git a/be/src/geo/wkt_parse_type.h b/be/src/geo/wkt_parse_type.h
index a871ce10217..97557cbf360 100644
--- a/be/src/geo/wkt_parse_type.h
+++ b/be/src/geo/wkt_parse_type.h
@@ -17,6 +17,8 @@
 
 #pragma once
 
+#include <memory>
+#include <utility>
 #include <vector>
 
 // This file include
@@ -33,15 +35,17 @@ struct GeoCoordinateList {
 };
 
 struct GeoCoordinateListList {
-    ~GeoCoordinateListList() {
-        for (auto item : list) {
-            delete item;
-        }
-    }
     GeoCoordinateListList() = default;
-    GeoCoordinateListList(GeoCoordinateListList&& other) : 
list(std::move(other.list)) {}
-    void add(GeoCoordinateList* coordinates) { list.push_back(coordinates); }
-    std::vector<GeoCoordinateList*> list;
+    GeoCoordinateListList(GeoCoordinateListList&& other) = default;
+    GeoCoordinateListList& operator=(GeoCoordinateListList&& other) = default;
+    GeoCoordinateListList(const GeoCoordinateListList&) = delete;
+    GeoCoordinateListList& operator=(const GeoCoordinateListList&) = delete;
+
+    void add(std::unique_ptr<GeoCoordinateList>&& coordinates) {
+        list.emplace_back(std::move(coordinates));
+    }
+
+    std::vector<std::unique_ptr<GeoCoordinateList>> list;
 };
 
 } // namespace doris
diff --git a/be/src/geo/wkt_yacc.y b/be/src/geo/wkt_yacc.y
index 02f59ea7068..a637bcca2e9 100644
--- a/be/src/geo/wkt_yacc.y
+++ b/be/src/geo/wkt_yacc.y
@@ -17,45 +17,67 @@
  * under the License.
  */
 
-%{
+// use C++ parser skeleton
+%language "c++"
+//use strong type, class encapsulated LALR(1) parser
+%skeleton "lalr1.cc"
+//store all values in std::variant (strong type)
+%define api.value.type variant
+//automatically generate constructor for tokens (convenient for C++)
+%define api.token.constructor
+//generated parser class is `wkt_::parser`
+%define api.prefix {wkt_}
+%defines
+
+/* ------------------------------
+ * 1. Headers and forward declarations placed in the .hpp file
+ *    **Generate location**:wkt_yacc.y.hpp(beginning)
+ *    **Useage**:Provide types and forward declarations for the parser and 
external callers
+ * ------------------------------ */
+%code requires {
+#include <memory>
+#include <variant>
+#include <vector>
+#include "geo/wkt_parse_ctx.h"   // we need WktParseContext to pass scaninfo 
to lexer
 #include "common/logging.h"
 #include "geo/wkt_parse_type.h"
 #include "geo/geo_types.h"
 
 struct WktParseContext;
-void wkt_error(WktParseContext* ctx, const char* msg) {
 }
-/* forward declare this class for wkt_parse declaration in yacc.y.cpp */
-%}
-
-%union {
-    double double_value;
-    doris::GeoCoordinate coordinate_value;
-    doris::GeoCoordinateList* coordinate_list_value;
-    doris::GeoCoordinateListList* coordinate_list_list_value;
-    std::vector<doris::GeoCoordinateListList>* multi_polygon_value;
-    doris::GeoShape* shape_value;
+
+/* ------------------------------
+ * 2. The function declarations provided to the lexer for calls are placed in 
the .hpp file.
+ *    **Generate location**:wkt_yacc.y.hpp(ending)
+ *    **Useage**:The lexer interacts with the parser, returning tokens.
+ * ------------------------------ */
+%code provides {
+wkt_::parser::symbol_type wkt_lex(WktParseContext* ctx, yyscan_t scanner);
 }
 
+/* ------------------------------
+ * 3. The parser member function implementation is placed in the .cpp file.
+ *    **Generate location**:wkt_yacc.y.cpp
+ *    **Useage**:Parser internal use, for example error() implementation
+ * ------------------------------ */
 %code {
-/* we need yyscan_t in WktParseContext, so we include lex.h here,
- * and we should include this header after union define, because it
- * need YYSTYPE
- */
-#include "geo/wkt_lex.l.h"
-/* we need WktParseContext to pass scaninfo to lexer */
-#include "geo/wkt_parse_ctx.h"
+#include <string>
+#include "common/exception.h"
 
-#define WKT_LEX_PARAM ctx->scaninfo
+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.
+    // 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) {}
+
+} // namespace wkt_
 }
 
-%define api.pure full
 %parse-param { WktParseContext* ctx }
-%lex-param { WKT_LEX_PARAM }
-
-/* for multi-thread */
-%define api.prefix {wkt_}
-%defines
+%parse-param { yyscan_t scanner }
+%lex-param { WktParseContext* ctx }
+%lex-param { yyscan_t scanner }
 
 %expect 0
 
@@ -65,45 +87,39 @@ void wkt_error(WktParseContext* ctx, const char* msg) {
 %token KW_POINT KW_LINESTRING KW_POLYGON
 %token KW_MULTI_POINT KW_MULTI_LINESTRING KW_MULTI_POLYGON
 
-%token <double_value> NUMERIC
-
-%type <None> shape
-%type <shape_value> point linestring polygon multi_polygon
-%type <coordinate_value> coordinate
-%type <coordinate_list_value> coordinate_list
-%type <coordinate_list_list_value> coordinate_list_list
-%type <multi_polygon_value> multi_polygon_list
+%token <double> NUMERIC
 
-%destructor { delete $$; } coordinate_list
-%destructor { delete $$; } coordinate_list_list
-%destructor { delete $$; } point
-%destructor { delete $$; } linestring
-%destructor { delete $$; } polygon
-%destructor { delete $$; } multi_polygon
-%destructor { delete $$; } multi_polygon_list
+%type <std::monostate> shape
+%type <std::unique_ptr<doris::GeoShape>> point linestring polygon multi_polygon
+%type <std::unique_ptr<doris::GeoCoordinate>> coordinate
+%type <std::unique_ptr<doris::GeoCoordinateList>> coordinate_list
+%type <std::unique_ptr<doris::GeoCoordinateListList>> coordinate_list_list
+%type <std::unique_ptr<std::vector<doris::GeoCoordinateListList>>> 
multi_polygon_list
 
 %%
 
 shape:
     point 
-    { ctx->shape = $1; }
+    { ctx->shape = std::move($1); }
     | linestring
-    { ctx->shape = $1; }
+    { ctx->shape = std::move($1); }
     | polygon
-    { ctx->shape = $1; }
+    { ctx->shape = std::move($1); }
     | multi_polygon
-    { ctx->shape = $1; }
+    { ctx->shape = std::move($1); }
     ;
 
 point:
      KW_POINT '(' coordinate ')'
      {
         std::unique_ptr<doris::GeoPoint> point = 
doris::GeoPoint::create_unique();
-        ctx->parse_status = point->from_coord($3);
+        const doris::GeoCoordinate& coord = *$3;
+        ctx->parse_status = point->from_coord(coord);
         if (ctx->parse_status != doris::GEO_PARSE_OK) {
             YYABORT;
         }
-        $$ = point.release();
+        std::unique_ptr<doris::GeoShape> shape = std::move(point);
+        
yylhs.value.emplace<std::unique_ptr<doris::GeoShape>>(std::move(shape));
      }
      ;
 
@@ -111,13 +127,14 @@ linestring:
     KW_LINESTRING '(' coordinate_list ')'
     {
         // to avoid memory leak
-        std::unique_ptr<doris::GeoCoordinateList> list($3);
+        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(*$3);
+        ctx->parse_status = line->from_coords(*list);
         if (ctx->parse_status != doris::GEO_PARSE_OK) {
             YYABORT;
         }
-        $$ = line.release();
+        std::unique_ptr<doris::GeoShape> shape = std::move(line);
+        
yylhs.value.emplace<std::unique_ptr<doris::GeoShape>>(std::move(shape));
     }
     ;
 
@@ -125,13 +142,14 @@ polygon:
     KW_POLYGON '(' coordinate_list_list ')'
     {
         // to avoid memory leak
-        std::unique_ptr<doris::GeoCoordinateListList> list($3);
+        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(*$3);
+        ctx->parse_status = polygon->from_coords(*list);
         if (ctx->parse_status != doris::GEO_PARSE_OK) {
             YYABORT;
         }
-        $$ = polygon.release();
+        std::unique_ptr<doris::GeoShape> shape = std::move(polygon);
+        
yylhs.value.emplace<std::unique_ptr<doris::GeoShape>>(std::move(shape));
     }
     ;
 
@@ -139,62 +157,75 @@ multi_polygon:
     KW_MULTI_POLYGON '(' multi_polygon_list ')'
     {
         // to avoid memory leak
-        std::unique_ptr<std::vector<doris::GeoCoordinateListList>> list($3);
+        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(*$3);
+        ctx->parse_status = multi_polygon->from_coords(*list);
         if (ctx->parse_status != doris::GEO_PARSE_OK) {
             YYABORT;
         }
-        $$ = multi_polygon.release();
+        std::unique_ptr<doris::GeoShape> shape = std::move(multi_polygon);
+        
yylhs.value.emplace<std::unique_ptr<doris::GeoShape>>(std::move(shape));
     }
     ;
 
 multi_polygon_list:
     multi_polygon_list ',' '(' coordinate_list_list ')'
     {
-        $1->push_back(std::move(*$4));
-        delete $4;
-        $$ = $1; 
+        auto vec = std::move($1);
+        auto list = std::move($4);
+        vec->push_back(std::move(*list));
+        
yylhs.value.emplace<std::unique_ptr<std::vector<doris::GeoCoordinateListList>>>(std::move(vec));
     }
     | '(' coordinate_list_list ')'
     {
-        $$ = new std::vector<doris::GeoCoordinateListList>();
-        $$->push_back(std::move(*$2));
-        delete $2;
+        auto list = std::move($2);
+        auto vec = 
std::make_unique<std::vector<doris::GeoCoordinateListList>>();
+        vec->push_back(std::move(*list));
+        
yylhs.value.emplace<std::unique_ptr<std::vector<doris::GeoCoordinateListList>>>(std::move(vec));
     }
     ;
 
 coordinate_list_list:
     coordinate_list_list ',' '(' coordinate_list ')'
     {
-        $1->add($4);
-        $$ = $1;
+        auto outer = std::move($1);
+        auto inner = std::move($4);
+        outer->add(std::move(inner));
+        
yylhs.value.emplace<std::unique_ptr<doris::GeoCoordinateListList>>(std::move(outer));
     }
     | '(' coordinate_list ')'
     {
-        $$ = new doris::GeoCoordinateListList();
-        $$->add($2);
+        auto inner = std::move($2);
+        auto outer = std::make_unique<doris::GeoCoordinateListList>();
+        outer->add(std::move(inner));
+        
yylhs.value.emplace<std::unique_ptr<doris::GeoCoordinateListList>>(std::move(outer));
     }
     ;
 
 coordinate_list:
     coordinate_list ',' coordinate
     { 
-        $1->add($3);
-        $$ = $1;
+        auto list = std::move($1);
+        auto coord = std::move($3);
+        list->add(*coord);
+        
yylhs.value.emplace<std::unique_ptr<doris::GeoCoordinateList>>(std::move(list));
     }
     | coordinate
     {
-        $$ = new doris::GeoCoordinateList();
-        $$->add($1);
+        auto coord = std::move($1);
+        auto list = std::make_unique<doris::GeoCoordinateList>();
+        list->add(*coord);
+        
yylhs.value.emplace<std::unique_ptr<doris::GeoCoordinateList>>(std::move(list));
     }
     ;
 
 coordinate:
     NUMERIC NUMERIC
     {
-        $$.x = $1;
-        $$.y = $2;
+        auto coord = std::make_unique<doris::GeoCoordinate>();
+        coord->x = $1;
+        coord->y = $2;
+        
yylhs.value.emplace<std::unique_ptr<doris::GeoCoordinate>>(std::move(coord));
     }
     ;
 
diff --git a/be/src/vec/functions/functions_geo.cpp 
b/be/src/vec/functions/functions_geo.cpp
index a688d104148..01b98957795 100644
--- a/be/src/vec/functions/functions_geo.cpp
+++ b/be/src/vec/functions/functions_geo.cpp
@@ -758,7 +758,7 @@ struct StGeoFromText {
         std::string buf;
         for (int row = 0; row < size; ++row) {
             auto value = geo->get_data_at(row);
-            std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(value.data, 
value.size, &status));
+            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)) {
                 null_map_data[row] = 1;
@@ -803,7 +803,7 @@ struct StGeoFromWkb {
         std::string buf;
         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));
+            std::unique_ptr<GeoShape> shape = GeoShape::from_wkb(value.data, 
value.size, status);
             if (shape == nullptr || status != GEO_PARSE_OK) {
                 null_map_data[row] = 1;
                 res->insert_default();
diff --git a/be/test/geo/geo_types_test.cpp b/be/test/geo/geo_types_test.cpp
index 5b4310f0ae6..cebb4f9296a 100644
--- a/be/test/geo/geo_types_test.cpp
+++ b/be/test/geo/geo_types_test.cpp
@@ -44,13 +44,13 @@ TEST_F(GeoTypesTest, point_normal) {
         std::string buf;
         point.encode_to(&buf);
         {
-            std::unique_ptr<GeoShape> 
point2(GeoShape::from_encoded(buf.data(), buf.size()));
+            auto point2 = GeoShape::from_encoded(buf.data(), buf.size());
             EXPECT_STREQ("POINT (116.123 63.546)", point2->as_wkt().c_str());
         }
 
         {
             buf.resize(buf.size() - 1);
-            std::unique_ptr<GeoShape> 
point2(GeoShape::from_encoded(buf.data(), buf.size()));
+            auto point2 = GeoShape::from_encoded(buf.data(), buf.size());
             EXPECT_EQ(nullptr, point2);
         }
     }
@@ -75,7 +75,7 @@ TEST_F(GeoTypesTest, point_invalid) {
 TEST_F(GeoTypesTest, linestring) {
     const char* wkt = "LINESTRING (30 10, 10 30, 40 40)";
     GeoParseStatus status;
-    std::unique_ptr<GeoShape> line(GeoShape::from_wkt(wkt, strlen(wkt), 
&status));
+    auto line = GeoShape::from_wkt(wkt, strlen(wkt), status);
     EXPECT_NE(nullptr, line.get());
     EXPECT_EQ(GEO_SHAPE_LINE_STRING, line->type());
 
@@ -85,12 +85,12 @@ TEST_F(GeoTypesTest, linestring) {
     line->encode_to(&buf);
 
     {
-        std::unique_ptr<GeoShape> line2(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto line2 = GeoShape::from_encoded(buf.data(), buf.size());
         EXPECT_STREQ(wkt, line2->as_wkt().c_str());
     }
     {
         buf.resize(buf.size() - 1);
-        std::unique_ptr<GeoShape> line2(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto line2 = GeoShape::from_encoded(buf.data(), buf.size());
         EXPECT_EQ(nullptr, line2);
     }
 }
@@ -102,12 +102,9 @@ TEST_F(GeoTypesTest, point_intersects) {
     const char* wkt_polygon = "POLYGON((0 0,10 0,10 10,0 10,0 0))";
     const char* wkt_multi_polygon = "MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 
0)))";
 
-    std::unique_ptr<GeoShape> line(
-            GeoShape::from_wkt(wkt_linestring, strlen(wkt_linestring), 
&status));
-    std::unique_ptr<GeoShape> polygon(
-            GeoShape::from_wkt(wkt_polygon, strlen(wkt_polygon), &status));
-    std::unique_ptr<GeoShape> multi_polygon(
-            GeoShape::from_wkt(wkt_multi_polygon, strlen(wkt_multi_polygon), 
&status));
+    auto line = GeoShape::from_wkt(wkt_linestring, strlen(wkt_linestring), 
status);
+    auto polygon = GeoShape::from_wkt(wkt_polygon, strlen(wkt_polygon), 
status);
+    auto multi_polygon = GeoShape::from_wkt(wkt_multi_polygon, 
strlen(wkt_multi_polygon), status);
     ASSERT_NE(nullptr, line.get());
     ASSERT_NE(nullptr, polygon.get());
     ASSERT_NE(nullptr, multi_polygon.get());
@@ -163,13 +160,13 @@ TEST_F(GeoTypesTest, point_intersects) {
     std::string buf;
     polygon->encode_to(&buf);
     {
-        std::unique_ptr<GeoShape> shape(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto shape = GeoShape::from_encoded(buf.data(), buf.size());
         ASSERT_NE(nullptr, shape.get());
         EXPECT_EQ(GEO_SHAPE_POLYGON, shape->type());
     }
     {
         buf.resize(buf.size() - 1);
-        std::unique_ptr<GeoShape> shape(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto shape = GeoShape::from_encoded(buf.data(), buf.size());
         EXPECT_EQ(nullptr, shape.get());
     }
 }
@@ -181,15 +178,13 @@ TEST_F(GeoTypesTest, linestring_intersects) {
     const char* vertical_line = "LINESTRING(0 -10, 0 10)";
     const char* polygon = "POLYGON((-5 -5,5 -5,5 5,-5 5,-5 -5))";
     const char* multi_polygon =
-            "MULTIPOLYGON(((30 30,35 30,35 35,30 35,30 30)), ((-5 -5,5 -5,5 
5,-5 5,-5 -5)))";
-
-    std::unique_ptr<GeoShape> base_line_shape(
-            GeoShape::from_wkt(base_line, strlen(base_line), &status));
-    std::unique_ptr<GeoShape> vertical_line_shape(
-            GeoShape::from_wkt(vertical_line, strlen(vertical_line), &status));
-    std::unique_ptr<GeoShape> polygon_shape(GeoShape::from_wkt(polygon, 
strlen(polygon), &status));
-    std::unique_ptr<GeoShape> multi_polygon_shape(
-            GeoShape::from_wkt(multi_polygon, strlen(multi_polygon), &status));
+            "MULTIPOLYGON(((30 30,35 30,35 35,30 35,30 30)), ((-5 -5,5 -5,5 
5,-5 5,-5 "
+            "-5)))";
+
+    auto base_line_shape = GeoShape::from_wkt(base_line, strlen(base_line), 
status);
+    auto vertical_line_shape = GeoShape::from_wkt(vertical_line, 
strlen(vertical_line), status);
+    auto polygon_shape = GeoShape::from_wkt(polygon, strlen(polygon), status);
+    auto multi_polygon_shape = GeoShape::from_wkt(multi_polygon, 
strlen(multi_polygon), status);
     ASSERT_NE(nullptr, base_line_shape.get());
     ASSERT_NE(nullptr, vertical_line_shape.get());
     ASSERT_NE(nullptr, polygon_shape.get());
@@ -223,36 +218,31 @@ TEST_F(GeoTypesTest, linestring_intersects) {
     {
         // crosswalks
         const char* wkt_string = "LINESTRING(-5 5,5 -5)";
-        std::unique_ptr<GeoShape> cross_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto cross_line = GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status);
         EXPECT_TRUE(base_line_shape->intersects(cross_line.get()));
     }
     {
         // partially overlapping lines
         const char* wkt_string = "LINESTRING(-5 0,5 0)";
-        std::unique_ptr<GeoShape> overlap_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto overlap_line = GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status);
         EXPECT_TRUE(base_line_shape->intersects(overlap_line.get()));
     }
     {
         // end contact line
         const char* wkt_string = "LINESTRING(10 0,10 10)";
-        std::unique_ptr<GeoShape> touch_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto touch_line = GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status);
         EXPECT_TRUE(base_line_shape->intersects(touch_line.get()));
     }
     {
         // end contact line
         const char* wkt_string = "LINESTRING(9 0,12 0)";
-        std::unique_ptr<GeoShape> touch_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto touch_line = GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status);
         EXPECT_TRUE(base_line_shape->intersects(touch_line.get()));
     }
     {
         // fully separated lines
         const char* wkt_string = "LINESTRING(0 5,10 5)";
-        std::unique_ptr<GeoShape> separate_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto separate_line = GeoShape::from_wkt(wkt_string, 
strlen(wkt_string), status);
         EXPECT_FALSE(base_line_shape->intersects(separate_line.get()));
     }
 
@@ -262,40 +252,35 @@ TEST_F(GeoTypesTest, linestring_intersects) {
     {
         // fully internal
         const char* wkt_string = "LINESTRING(-2 0,2 0)";
-        std::unique_ptr<GeoShape> inner_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto inner_line = GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status);
         EXPECT_TRUE(polygon_shape->intersects(inner_line.get()));
         EXPECT_TRUE(multi_polygon_shape->intersects(inner_line.get()));
     }
     {
         // crossing the border
         const char* wkt_string = "LINESTRING(-10 0,10 0)";
-        std::unique_ptr<GeoShape> cross_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto cross_line = GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status);
         EXPECT_TRUE(polygon_shape->intersects(cross_line.get()));
         EXPECT_TRUE(multi_polygon_shape->intersects(cross_line.get()));
     }
     {
         // along the borderline
         const char* wkt_string = "LINESTRING(-5 -5,5 -5)";
-        std::unique_ptr<GeoShape> edge_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto edge_line = GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status);
         EXPECT_TRUE(polygon_shape->intersects(edge_line.get()));
         EXPECT_TRUE(multi_polygon_shape->intersects(edge_line.get()));
     }
     {
         // only one point
         const char* wkt_string = "LINESTRING(-5 -5,-5 -10)";
-        std::unique_ptr<GeoShape> edge_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto edge_line = GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status);
         EXPECT_TRUE(polygon_shape->intersects(edge_line.get()));
         EXPECT_TRUE(multi_polygon_shape->intersects(edge_line.get()));
     }
     {
         // fully external
         const char* wkt_string = "LINESTRING(10 10,20 20)";
-        std::unique_ptr<GeoShape> outer_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto outer_line = GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status);
         EXPECT_FALSE(polygon_shape->intersects(outer_line.get()));
         EXPECT_FALSE(multi_polygon_shape->intersects(outer_line.get()));
     }
@@ -303,13 +288,13 @@ TEST_F(GeoTypesTest, linestring_intersects) {
     std::string buf;
     base_line_shape->encode_to(&buf);
     {
-        std::unique_ptr<GeoShape> decoded(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto decoded(GeoShape::from_encoded(buf.data(), buf.size()));
         ASSERT_NE(nullptr, decoded.get());
         EXPECT_EQ(GEO_SHAPE_LINE_STRING, decoded->type());
     }
     {
         buf.resize(buf.size() - 2);
-        std::unique_ptr<GeoShape> decoded(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto decoded(GeoShape::from_encoded(buf.data(), buf.size()));
         EXPECT_EQ(nullptr, decoded.get());
     }
 }
@@ -324,15 +309,11 @@ TEST_F(GeoTypesTest, polygon_intersects) {
     const char* multi_polygons =
             "MULTIPOLYGON(((35 35,40 35,40 40,35 40,35 35)), ((0 0,10 0,10 
10,0 10,0 0)))";
 
-    std::unique_ptr<GeoShape> polygon(
-            GeoShape::from_wkt(base_polygon, strlen(base_polygon), &status));
-    std::unique_ptr<GeoShape> polygon2(
-            GeoShape::from_wkt(base_polygon2, strlen(base_polygon2), &status));
-    std::unique_ptr<GeoShape> line(GeoShape::from_wkt(test_line, 
strlen(test_line), &status));
-    std::unique_ptr<GeoShape> other_polygon(
-            GeoShape::from_wkt(overlap_polygon, strlen(overlap_polygon), 
&status));
-    std::unique_ptr<GeoShape> multi_polygon(
-            GeoShape::from_wkt(multi_polygons, strlen(multi_polygons), 
&status));
+    auto polygon = GeoShape::from_wkt(base_polygon, strlen(base_polygon), 
status);
+    auto polygon2 = GeoShape::from_wkt(base_polygon2, strlen(base_polygon2), 
status);
+    auto line = GeoShape::from_wkt(test_line, strlen(test_line), status);
+    auto other_polygon = GeoShape::from_wkt(overlap_polygon, 
strlen(overlap_polygon), status);
+    auto multi_polygon = GeoShape::from_wkt(multi_polygons, 
strlen(multi_polygons), status);
     ASSERT_NE(nullptr, polygon.get());
     ASSERT_NE(nullptr, polygon2.get());
     ASSERT_NE(nullptr, line.get());
@@ -387,75 +368,68 @@ TEST_F(GeoTypesTest, polygon_intersects) {
     // Polygon vs LineString
     // ======================
     {
-        const char* wkt = "LINESTRING(2 2,8 8)";
-        std::unique_ptr<GeoShape> inner_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        const char* wkt_line = "LINESTRING(2 2,8 8)";
+        auto inner_line = GeoShape::from_wkt(wkt_line, strlen(wkt_line), 
status);
         EXPECT_TRUE(polygon->intersects(inner_line.get()));
     }
     {
-        const char* wkt = "LINESTRING(-5 5,15 5)";
-        std::unique_ptr<GeoShape> cross_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        const char* wkt_line = "LINESTRING(-5 5,15 5)";
+        auto cross_line = GeoShape::from_wkt(wkt_line, strlen(wkt_line), 
status);
         EXPECT_TRUE(polygon->intersects(cross_line.get()));
     }
     {
-        const char* wkt = "LINESTRING(0 0,10 0)";
-        std::unique_ptr<GeoShape> edge_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        const char* wkt_line = "LINESTRING(0 0,10 0)";
+        auto edge_line = GeoShape::from_wkt(wkt_line, strlen(wkt_line), 
status);
         EXPECT_TRUE(polygon->intersects(edge_line.get()));
     }
     {
-        const char* wkt = "LINESTRING(0 0.1,10 0.1)";
-        std::unique_ptr<GeoShape> edge_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        const char* wkt_line = "LINESTRING(0 0.1,10 0.1)";
+        auto edge_line = GeoShape::from_wkt(wkt_line, strlen(wkt_line), 
status);
         EXPECT_TRUE(polygon->intersects(edge_line.get()));
     }
     {
-        const char* wkt = "LINESTRING(0 -0.1,10 -0.1)";
-        std::unique_ptr<GeoShape> edge_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        const char* wkt_line = "LINESTRING(0 -0.1,10 -0.1)";
+        auto edge_line = GeoShape::from_wkt(wkt_line, strlen(wkt_line), 
status);
         EXPECT_FALSE(polygon->intersects(edge_line.get()));
     }
     {
-        const char* wkt = "LINESTRING(0.1 0,0.1 10)";
-        std::unique_ptr<GeoShape> edge_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        const char* wkt_line = "LINESTRING(0.1 0,0.1 10)";
+        auto edge_line = GeoShape::from_wkt(wkt_line, strlen(wkt_line), 
status);
         EXPECT_TRUE(polygon->intersects(edge_line.get()));
     }
     {
-        const char* wkt = "LINESTRING(-0.1 0,-0.1 10)";
-        std::unique_ptr<GeoShape> edge_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        const char* wkt_line = "LINESTRING(-0.1 0,-0.1 10)";
+        auto edge_line = GeoShape::from_wkt(wkt_line, strlen(wkt_line), 
status);
         EXPECT_FALSE(polygon->intersects(edge_line.get()));
     }
     {
-        const char* wkt = "LINESTRING(0 10.1,10 10.1)";
-        std::unique_ptr<GeoShape> edge_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        const char* wkt_line = "LINESTRING(0 10.1,10 10.1)";
+        auto edge_line = GeoShape::from_wkt(wkt_line, strlen(wkt_line), 
status);
         EXPECT_FALSE(polygon->intersects(edge_line.get()));
     }
     {
-        const char* wkt = "LINESTRING(0 9.99,10 9.99)";
-        std::unique_ptr<GeoShape> edge_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        const char* wkt_line = "LINESTRING(0 9.99,10 9.99)";
+        auto edge_line = GeoShape::from_wkt(wkt_line, strlen(wkt_line), 
status);
         EXPECT_TRUE(polygon->intersects(edge_line.get()));
     }
     {
-        const char* wkt = "LINESTRING(20 20,30 30)";
-        std::unique_ptr<GeoShape> outer_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        const char* wkt_line = "LINESTRING(20 20,30 30)";
+        auto outer_line = GeoShape::from_wkt(wkt_line, strlen(wkt_line), 
status);
         EXPECT_FALSE(polygon->intersects(outer_line.get()));
     }
-
     {
-        // along the borderline
-        const char* wkt_string = "LINESTRING(-20 -5.01, 20 -5.01)";
-        std::unique_ptr<GeoShape> edge_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        const char* wkt_line = "LINESTRING(-20 -5.01, 20 -5.01)";
+        auto edge_line = GeoShape::from_wkt(wkt_line, strlen(wkt_line), 
status);
         EXPECT_FALSE(polygon2->intersects(edge_line.get()));
     }
     {
-        // along the borderline
-        const char* wkt_string = "LINESTRING(-20 -4.9, 20 -4.9)";
-        std::unique_ptr<GeoShape> edge_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        const char* wkt_line = "LINESTRING(-20 -4.9, 20 -4.9)";
+        auto edge_line = GeoShape::from_wkt(wkt_line, strlen(wkt_line), 
status);
         EXPECT_TRUE(polygon2->intersects(edge_line.get()));
     }
     {
-        // along the borderline
-        const char* wkt_string = "LINESTRING(-20 -5,20 -5)";
-        std::unique_ptr<GeoShape> edge_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        const char* wkt_line = "LINESTRING(-20 -5, 20 -5)";
+        auto edge_line = GeoShape::from_wkt(wkt_line, strlen(wkt_line), 
status);
         EXPECT_TRUE(polygon2->intersects(edge_line.get()));
     }
 
@@ -463,26 +437,26 @@ TEST_F(GeoTypesTest, polygon_intersects) {
     // Polygon vs Polygon
     // ======================
     {
-        const char* wkt = "POLYGON((2 2,8 2,8 8,2 8,2 2))";
-        std::unique_ptr<GeoShape> small_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        const char* wkt_poly = "POLYGON((2 2,8 2,8 8,2 8,2 2))";
+        auto small_polygon = GeoShape::from_wkt(wkt_poly, strlen(wkt_poly), 
status);
         EXPECT_TRUE(polygon->intersects(small_polygon.get()));
         EXPECT_TRUE(multi_polygon->intersects(small_polygon.get()));
     }
     {
-        const char* wkt = "POLYGON((5 5,15 5,15 15,5 15,5 5))";
-        std::unique_ptr<GeoShape> overlap_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
-        EXPECT_TRUE(polygon->intersects(overlap_polygon.get()));
-        EXPECT_TRUE(multi_polygon->intersects(overlap_polygon.get()));
+        auto overlap_polygon_shape =
+                GeoShape::from_wkt(overlap_polygon, strlen(overlap_polygon), 
status);
+        EXPECT_TRUE(polygon->intersects(overlap_polygon_shape.get()));
+        EXPECT_TRUE(multi_polygon->intersects(overlap_polygon_shape.get()));
     }
     {
-        const char* wkt = "POLYGON((10 0,20 0,20 10,10 10,10 0))";
-        std::unique_ptr<GeoShape> touch_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        const char* wkt_poly = "POLYGON((10 0,20 0,20 10,10 10,10 0))";
+        auto touch_polygon = GeoShape::from_wkt(wkt_poly, strlen(wkt_poly), 
status);
         EXPECT_TRUE(polygon->intersects(touch_polygon.get()));
         EXPECT_TRUE(multi_polygon->intersects(touch_polygon.get()));
     }
     {
-        const char* wkt = "POLYGON((20 20,30 20,30 30,20 30,20 20))";
-        std::unique_ptr<GeoShape> separate_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        const char* wkt_poly = "POLYGON((20 20,30 20,30 30,20 30,20 20))";
+        auto separate_polygon = GeoShape::from_wkt(wkt_poly, strlen(wkt_poly), 
status);
         EXPECT_FALSE(polygon->intersects(separate_polygon.get()));
         EXPECT_FALSE(multi_polygon->intersects(separate_polygon.get()));
     }
@@ -490,13 +464,13 @@ TEST_F(GeoTypesTest, polygon_intersects) {
     std::string buf;
     polygon->encode_to(&buf);
     {
-        std::unique_ptr<GeoShape> decoded(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto decoded = GeoShape::from_encoded(buf.data(), buf.size());
         ASSERT_NE(nullptr, decoded.get());
         EXPECT_EQ(GEO_SHAPE_POLYGON, decoded->type());
     }
     {
         buf.resize(buf.size() - 2);
-        std::unique_ptr<GeoShape> decoded(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto decoded = GeoShape::from_encoded(buf.data(), buf.size());
         EXPECT_EQ(nullptr, decoded.get());
     }
 }
@@ -515,13 +489,10 @@ TEST_F(GeoTypesTest, multipolygon_intersects) {
     const char* overlap_polygon = "POLYGON((8 8, 18 8, 18 18, 8 18, 8 8))";
     const char* external_polygon = "POLYGON((50 50, 60 50, 60 60, 50 60, 50 
50))";
 
-    std::unique_ptr<GeoShape> multipolygon(
-            GeoShape::from_wkt(base_multipolygon, strlen(base_multipolygon), 
&status));
-    std::unique_ptr<GeoShape> line(GeoShape::from_wkt(test_line, 
strlen(test_line), &status));
-    std::unique_ptr<GeoShape> poly_overlap(
-            GeoShape::from_wkt(overlap_polygon, strlen(overlap_polygon), 
&status));
-    std::unique_ptr<GeoShape> poly_external(
-            GeoShape::from_wkt(external_polygon, strlen(external_polygon), 
&status));
+    auto multipolygon = GeoShape::from_wkt(base_multipolygon, 
strlen(base_multipolygon), status);
+    auto line = GeoShape::from_wkt(test_line, strlen(test_line), status);
+    auto poly_overlap = GeoShape::from_wkt(overlap_polygon, 
strlen(overlap_polygon), status);
+    auto poly_external = GeoShape::from_wkt(external_polygon, 
strlen(external_polygon), status);
 
     ASSERT_NE(nullptr, multipolygon.get());
     ASSERT_NE(nullptr, line.get());
@@ -562,27 +533,27 @@ TEST_F(GeoTypesTest, multipolygon_intersects) {
     // ======================
     {
         const char* wkt = "LINESTRING(4 4, 7 7)";
-        std::unique_ptr<GeoShape> in_hole_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto in_hole_line = GeoShape::from_wkt(wkt, strlen(wkt), status);
         EXPECT_FALSE(multipolygon->intersects(in_hole_line.get()));
     }
     {
         const char* wkt = "LINESTRING(-5 5, 35 5)";
-        std::unique_ptr<GeoShape> cross_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto cross_line = GeoShape::from_wkt(wkt, strlen(wkt), status);
         EXPECT_TRUE(multipolygon->intersects(cross_line.get()));
     }
     {
         const char* wkt = "LINESTRING(3 3, 7 3)";
-        std::unique_ptr<GeoShape> inner_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto inner_line = GeoShape::from_wkt(wkt, strlen(wkt), status);
         EXPECT_TRUE(multipolygon->intersects(inner_line.get()));
     }
     {
         const char* wkt = "LINESTRING(30 30, 35 35)";
-        std::unique_ptr<GeoShape> triangle_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto triangle_line = GeoShape::from_wkt(wkt, strlen(wkt), status);
         EXPECT_TRUE(multipolygon->intersects(triangle_line.get()));
     }
     {
         const char* wkt = "LINESTRING(50 50, 60 60)";
-        std::unique_ptr<GeoShape> outer_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto outer_line = GeoShape::from_wkt(wkt, strlen(wkt), status);
         EXPECT_FALSE(multipolygon->intersects(outer_line.get()));
     }
 
@@ -591,27 +562,27 @@ TEST_F(GeoTypesTest, multipolygon_intersects) {
     // ======================
     {
         const char* wkt = "POLYGON((4 4, 7 4, 7 7, 4 7, 4 4))";
-        std::unique_ptr<GeoShape> in_hole_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto in_hole_polygon = GeoShape::from_wkt(wkt, strlen(wkt), status);
         EXPECT_FALSE(multipolygon->intersects(in_hole_polygon.get()));
     }
     {
         const char* wkt = "POLYGON((20 0, 30 0, 30 10, 20 10, 20 0))";
-        std::unique_ptr<GeoShape> overlap_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
-        EXPECT_TRUE(multipolygon->intersects(overlap_polygon.get()));
+        auto overlap_polygon_shape = GeoShape::from_wkt(wkt, strlen(wkt), 
status);
+        EXPECT_TRUE(multipolygon->intersects(overlap_polygon_shape.get()));
     }
     {
         const char* wkt = "POLYGON((50 50, 60 50, 60 60, 50 60, 50 50))";
-        std::unique_ptr<GeoShape> external_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
-        EXPECT_FALSE(multipolygon->intersects(external_polygon.get()));
+        auto external_polygon_shape = GeoShape::from_wkt(wkt, strlen(wkt), 
status);
+        EXPECT_FALSE(multipolygon->intersects(external_polygon_shape.get()));
     }
     {
         const char* wkt = "POLYGON((10 0, 20 0, 20 5, 10 5, 10 0))";
-        std::unique_ptr<GeoShape> cross_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto cross_polygon = GeoShape::from_wkt(wkt, strlen(wkt), status);
         EXPECT_TRUE(multipolygon->intersects(cross_polygon.get()));
     }
     {
         const char* wkt = "POLYGON((10 0, 15 0, 15 10, 10 10, 10 0))";
-        std::unique_ptr<GeoShape> touch_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto touch_polygon = GeoShape::from_wkt(wkt, strlen(wkt), status);
         EXPECT_TRUE(multipolygon->intersects(touch_polygon.get()));
     }
 
@@ -620,27 +591,30 @@ TEST_F(GeoTypesTest, multipolygon_intersects) {
     // ======================
     {
         const char* wkt = "MULTIPOLYGON (((4 4, 5 4, 5 5, 4 5, 4 4)), ((6 6, 7 
6, 7 7, 6 7, 6 6)))";
-        std::unique_ptr<GeoShape> in_hole_multi(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto in_hole_multi = GeoShape::from_wkt(wkt, strlen(wkt), status);
         EXPECT_FALSE(multipolygon->intersects(in_hole_multi.get()));
     }
     {
         const char* wkt =
-                "MULTIPOLYGON (((8 8, 18 8, 18 18, 8 18, 8 8)), ((30 30, 40 
30, 35 35, 30 30)))";
-        std::unique_ptr<GeoShape> overlap_multi(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+                "MULTIPOLYGON (((8 8, 18 8, 18 18, 8 18, 8 8)), ((30 30, 40 
30, 35 35, 30 "
+                "30)))";
+        auto overlap_multi = GeoShape::from_wkt(wkt, strlen(wkt), status);
         EXPECT_TRUE(multipolygon->intersects(overlap_multi.get()));
     }
     {
         const char* wkt =
-                "MULTIPOLYGON (((-10 -10, 0 -10, 0 0, -10 0, -10 -10)), ((50 
50, 60 50, 60 60, 50 "
+                "MULTIPOLYGON (((-10 -10, 0 -10, 0 0, -10 0, -10 -10)), ((50 
50, 60 50, 60 "
+                "60, "
+                "50 "
                 "60, 50 50)))";
-        std::unique_ptr<GeoShape> separate_multi(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto separate_multi = GeoShape::from_wkt(wkt, strlen(wkt), status);
         EXPECT_TRUE(multipolygon->intersects(separate_multi.get()));
     }
 
     std::string buf;
     multipolygon->encode_to(&buf);
     {
-        std::unique_ptr<GeoShape> decoded(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto decoded = GeoShape::from_encoded(buf.data(), buf.size());
         ASSERT_NE(nullptr, decoded.get());
         EXPECT_EQ(GEO_SHAPE_MULTI_POLYGON, decoded->type());
 
@@ -650,7 +624,7 @@ TEST_F(GeoTypesTest, multipolygon_intersects) {
     }
     {
         buf.resize(buf.size() - 2);
-        std::unique_ptr<GeoShape> decoded(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto decoded = GeoShape::from_encoded(buf.data(), buf.size());
         EXPECT_EQ(nullptr, decoded.get());
     }
 }
@@ -691,12 +665,12 @@ TEST_F(GeoTypesTest, circle_intersect) {
     // ======================
     {
         const char* wkt = "LINESTRING(-20 0, 20 0)";
-        std::unique_ptr<GeoShape> line(GeoShape::from_wkt(wkt, strlen(wkt), 
&status));
+        auto line(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(circle.intersects(line.get()));
     }
     {
         const char* wkt = "LINESTRING(20 20, 30 30)";
-        std::unique_ptr<GeoShape> line(GeoShape::from_wkt(wkt, strlen(wkt), 
&status));
+        auto line(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(circle.intersects(line.get()));
     }
 
@@ -705,12 +679,12 @@ TEST_F(GeoTypesTest, circle_intersect) {
     // ======================
     {
         const char* wkt = "POLYGON((-5 -5,5 -5,5 5,-5 5,-5 -5))";
-        std::unique_ptr<GeoShape> poly(GeoShape::from_wkt(wkt, strlen(wkt), 
&status));
+        auto poly(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(circle.intersects(poly.get()));
     }
     {
         const char* wkt = "POLYGON((20 20,30 20,30 30,20 30,20 20))";
-        std::unique_ptr<GeoShape> poly(GeoShape::from_wkt(wkt, strlen(wkt), 
&status));
+        auto poly(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(circle.intersects(poly.get()));
     }
 
@@ -736,12 +710,9 @@ TEST_F(GeoTypesTest, point_touches) {
     const char* wkt_polygon = "POLYGON((0 0,10 0,10 10,0 10,0 0))";
     const char* wkt_multi_polygon = "MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 
0)))";
 
-    std::unique_ptr<GeoShape> line(
-            GeoShape::from_wkt(wkt_linestring, strlen(wkt_linestring), 
&status));
-    std::unique_ptr<GeoShape> polygon(
-            GeoShape::from_wkt(wkt_polygon, strlen(wkt_polygon), &status));
-    std::unique_ptr<GeoShape> multi_polygon(
-            GeoShape::from_wkt(wkt_multi_polygon, strlen(wkt_multi_polygon), 
&status));
+    auto line = GeoShape::from_wkt(wkt_linestring, strlen(wkt_linestring), 
status);
+    auto polygon = GeoShape::from_wkt(wkt_polygon, strlen(wkt_polygon), 
status);
+    auto multi_polygon = GeoShape::from_wkt(wkt_multi_polygon, 
strlen(wkt_multi_polygon), status);
     ASSERT_NE(nullptr, line.get());
     ASSERT_NE(nullptr, polygon.get());
     ASSERT_NE(nullptr, multi_polygon.get());
@@ -797,13 +768,13 @@ TEST_F(GeoTypesTest, point_touches) {
     std::string buf;
     polygon->encode_to(&buf);
     {
-        std::unique_ptr<GeoShape> shape(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto shape = GeoShape::from_encoded(buf.data(), buf.size());
         ASSERT_NE(nullptr, shape.get());
         EXPECT_EQ(GEO_SHAPE_POLYGON, shape->type());
     }
     {
         buf.resize(buf.size() - 1);
-        std::unique_ptr<GeoShape> shape(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto shape = GeoShape::from_encoded(buf.data(), buf.size());
         EXPECT_EQ(nullptr, shape.get());
     }
 }
@@ -816,13 +787,10 @@ TEST_F(GeoTypesTest, linestring_touches) {
     const char* polygon = "POLYGON((-5 -5,5 -5,5 5,-5 5,-5 -5))";
     const char* multi_polygon = "MULTIPOLYGON(((-5 -5,5 -5,5 5,-5 5,-5 -5)))";
 
-    std::unique_ptr<GeoShape> base_line_shape(
-            GeoShape::from_wkt(base_line, strlen(base_line), &status));
-    std::unique_ptr<GeoShape> vertical_line_shape(
-            GeoShape::from_wkt(vertical_line, strlen(vertical_line), &status));
-    std::unique_ptr<GeoShape> polygon_shape(GeoShape::from_wkt(polygon, 
strlen(polygon), &status));
-    std::unique_ptr<GeoShape> multi_polygon_shape(
-            GeoShape::from_wkt(multi_polygon, strlen(multi_polygon), &status));
+    auto base_line_shape = GeoShape::from_wkt(base_line, strlen(base_line), 
status);
+    auto vertical_line_shape = GeoShape::from_wkt(vertical_line, 
strlen(vertical_line), status);
+    auto polygon_shape = GeoShape::from_wkt(polygon, strlen(polygon), status);
+    auto multi_polygon_shape = GeoShape::from_wkt(multi_polygon, 
strlen(multi_polygon), status);
     ASSERT_NE(nullptr, base_line_shape.get());
     ASSERT_NE(nullptr, vertical_line_shape.get());
     ASSERT_NE(nullptr, polygon_shape.get());
@@ -856,43 +824,37 @@ TEST_F(GeoTypesTest, linestring_touches) {
     {
         // crosswalks
         const char* wkt_string = "LINESTRING(-5 5, 5 -5)";
-        std::unique_ptr<GeoShape> cross_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto cross_line(GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status));
         EXPECT_FALSE(base_line_shape->touches(cross_line.get()));
     }
     {
         // partially overlapping lines
         const char* wkt_string = "LINESTRING(-5 0, 5 0)";
-        std::unique_ptr<GeoShape> overlap_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto overlap_line = GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status);
         EXPECT_FALSE(base_line_shape->touches(overlap_line.get()));
     }
     {
         // end contact line
         const char* wkt_string = "LINESTRING(10 0, 12 0)";
-        std::unique_ptr<GeoShape> touch_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto touch_line = GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status);
         EXPECT_TRUE(base_line_shape->touches(touch_line.get()));
     }
     {
         // end intersect line
         const char* wkt_string = "LINESTRING(9 0, 10 0)";
-        std::unique_ptr<GeoShape> touch_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto touch_line = GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status);
         EXPECT_FALSE(base_line_shape->touches(touch_line.get()));
     }
     {
         // end intersect line
         const char* wkt_string = "LINESTRING(-10 0, 10 0)";
-        std::unique_ptr<GeoShape> touch_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto touch_line(GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status));
         EXPECT_FALSE(base_line_shape->touches(touch_line.get()));
     }
     {
         // fully separated lines
         const char* wkt_string = "LINESTRING(0 5, 10 5)";
-        std::unique_ptr<GeoShape> separate_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto separate_line(GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status));
         EXPECT_FALSE(base_line_shape->touches(separate_line.get()));
     }
 
@@ -902,56 +864,49 @@ TEST_F(GeoTypesTest, linestring_touches) {
     {
         // fully internal
         const char* wkt_string = "LINESTRING(-2 0,2 0)";
-        std::unique_ptr<GeoShape> inner_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto inner_line(GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status));
         EXPECT_FALSE(polygon_shape->touches(inner_line.get()));
         EXPECT_FALSE(multi_polygon_shape->touches(inner_line.get()));
     }
     {
         // crossing the border
         const char* wkt_string = "LINESTRING(-10 0, 10 0)";
-        std::unique_ptr<GeoShape> cross_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto cross_line(GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status));
         EXPECT_FALSE(polygon_shape->touches(cross_line.get()));
         EXPECT_FALSE(multi_polygon_shape->touches(cross_line.get()));
     }
     {
         // along the borderline
         const char* wkt_string = "LINESTRING(-5 -5, 5 -5)";
-        std::unique_ptr<GeoShape> edge_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto edge_line(GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status));
         EXPECT_TRUE(polygon_shape->touches(edge_line.get()));
         EXPECT_TRUE(multi_polygon_shape->touches(edge_line.get()));
     }
     {
         // along the borderline
         const char* wkt_string = "LINESTRING(-20 -5.01, 20 -5.01)";
-        std::unique_ptr<GeoShape> edge_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto edge_line(GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status));
         EXPECT_FALSE(polygon_shape->touches(edge_line.get()));
         EXPECT_FALSE(multi_polygon_shape->touches(edge_line.get()));
     }
     {
         // along the borderline
         const char* wkt_string = "LINESTRING(-20 -4.99, 20 -4.99)";
-        std::unique_ptr<GeoShape> edge_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto edge_line(GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status));
         EXPECT_FALSE(polygon_shape->touches(edge_line.get()));
         EXPECT_FALSE(multi_polygon_shape->touches(edge_line.get()));
     }
     {
         // along the borderline
         const char* wkt_string = "LINESTRING(-20 -5,20 -5)";
-        std::unique_ptr<GeoShape> edge_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto edge_line(GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status));
         EXPECT_TRUE(polygon_shape->touches(edge_line.get()));
         EXPECT_TRUE(multi_polygon_shape->touches(edge_line.get()));
     }
     {
         // fully external
         const char* wkt_string = "LINESTRING(10 10,20 20)";
-        std::unique_ptr<GeoShape> outer_line(
-                GeoShape::from_wkt(wkt_string, strlen(wkt_string), &status));
+        auto outer_line(GeoShape::from_wkt(wkt_string, strlen(wkt_string), 
status));
         EXPECT_FALSE(polygon_shape->touches(outer_line.get()));
         EXPECT_FALSE(multi_polygon_shape->touches(outer_line.get()));
     }
@@ -959,13 +914,13 @@ TEST_F(GeoTypesTest, linestring_touches) {
     std::string buf;
     base_line_shape->encode_to(&buf);
     {
-        std::unique_ptr<GeoShape> decoded(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto decoded(GeoShape::from_encoded(buf.data(), buf.size()));
         ASSERT_NE(nullptr, decoded.get());
         EXPECT_EQ(GEO_SHAPE_LINE_STRING, decoded->type());
     }
     {
         buf.resize(buf.size() - 2);
-        std::unique_ptr<GeoShape> decoded(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto decoded(GeoShape::from_encoded(buf.data(), buf.size()));
         EXPECT_EQ(nullptr, decoded.get());
     }
 }
@@ -980,12 +935,12 @@ TEST_F(GeoTypesTest, polygon_touches) {
             "MULTIPOLYGON(((30 30,35 30,35 35,30 35,30 30)), ((0 0,10 0,10 
10,0 10,0 0)))";
 
     std::unique_ptr<GeoShape> polygon(
-            GeoShape::from_wkt(base_polygon, strlen(base_polygon), &status));
-    std::unique_ptr<GeoShape> line(GeoShape::from_wkt(test_line, 
strlen(test_line), &status));
+            GeoShape::from_wkt(base_polygon, strlen(base_polygon), status));
+    std::unique_ptr<GeoShape> line(GeoShape::from_wkt(test_line, 
strlen(test_line), status));
     std::unique_ptr<GeoShape> other_polygon(
-            GeoShape::from_wkt(overlap_polygon, strlen(overlap_polygon), 
&status));
+            GeoShape::from_wkt(overlap_polygon, strlen(overlap_polygon), 
status));
     std::unique_ptr<GeoShape> multi_polygon(
-            GeoShape::from_wkt(test_multi_polugon, strlen(test_multi_polugon), 
&status));
+            GeoShape::from_wkt(test_multi_polugon, strlen(test_multi_polugon), 
status));
     ASSERT_NE(nullptr, polygon.get());
     ASSERT_NE(nullptr, line.get());
     ASSERT_NE(nullptr, other_polygon.get());
@@ -1020,47 +975,47 @@ TEST_F(GeoTypesTest, polygon_touches) {
     // ======================
     {
         const char* wkt = "LINESTRING(2 2,8 8)";
-        std::unique_ptr<GeoShape> inner_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto inner_line(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(polygon->touches(inner_line.get()));
     }
     {
         const char* wkt = "LINESTRING(-5 5,15 5)";
-        std::unique_ptr<GeoShape> cross_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto cross_line(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(polygon->touches(cross_line.get()));
     }
     {
         const char* wkt = "LINESTRING(10 5, 15 5)";
-        std::unique_ptr<GeoShape> cross_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto cross_line(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(polygon->touches(cross_line.get()));
     }
     {
         const char* wkt = "LINESTRING(5 5, 15 15)";
-        std::unique_ptr<GeoShape> cross_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto cross_line(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(polygon->touches(cross_line.get()));
     }
     {
         const char* wkt = "LINESTRING(10 10, 15 15)";
-        std::unique_ptr<GeoShape> cross_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto cross_line(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(polygon->touches(cross_line.get()));
     }
     {
         const char* wkt = "LINESTRING(0 0, 5 0)";
-        std::unique_ptr<GeoShape> edge_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto edge_line(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(polygon->touches(edge_line.get()));
     }
     {
         const char* wkt = "LINESTRING(2 0, 5 0)";
-        std::unique_ptr<GeoShape> edge_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto edge_line(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(polygon->touches(edge_line.get()));
     }
     {
         const char* wkt = "LINESTRING(0 0,10 0)";
-        std::unique_ptr<GeoShape> edge_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto edge_line(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(polygon->touches(edge_line.get()));
     }
     {
         const char* wkt = "LINESTRING(20 20,30 30)";
-        std::unique_ptr<GeoShape> outer_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto outer_line(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(polygon->touches(outer_line.get()));
     }
 
@@ -1069,32 +1024,32 @@ TEST_F(GeoTypesTest, polygon_touches) {
     // ======================
     {
         const char* wkt = "POLYGON((2 2,8 2,8 8,2 8,2 2))";
-        std::unique_ptr<GeoShape> small_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto small_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(polygon->touches(small_polygon.get()));
     }
     {
         const char* wkt = "POLYGON((5 5,15 5,15 15,5 15,5 5))";
-        std::unique_ptr<GeoShape> overlap_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto overlap_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(polygon->touches(overlap_polygon.get()));
     }
     {
         const char* wkt = "POLYGON((10 0,20 0,20 10,10 10,10 0))";
-        std::unique_ptr<GeoShape> touch_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto touch_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(polygon->touches(touch_polygon.get()));
     }
     {
         const char* wkt = "POLYGON((10.1 0,20 0,20 10,10.1 10,10.1 0))";
-        std::unique_ptr<GeoShape> touch_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto touch_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(polygon->touches(touch_polygon.get()));
     }
     {
         const char* wkt = "POLYGON((9.99 0,20 0,20 10,9.99 10,9.99 0))";
-        std::unique_ptr<GeoShape> touch_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto touch_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(polygon->touches(touch_polygon.get()));
     }
     {
         const char* wkt = "POLYGON((20 20,30 20,30 30,20 30,20 20))";
-        std::unique_ptr<GeoShape> separate_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto separate_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(polygon->touches(separate_polygon.get()));
     }
 
@@ -1103,45 +1058,45 @@ TEST_F(GeoTypesTest, polygon_touches) {
     // ========================
     {
         const char* wkt = "MULTIPOLYGON(((2 2,8 2,8 8,2 8,2 2)))";
-        std::unique_ptr<GeoShape> small_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto small_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(polygon->touches(small_polygon.get()));
     }
     {
         const char* wkt = "MULTIPOLYGON(((5 5,15 5,15 15,5 15,5 5)))";
-        std::unique_ptr<GeoShape> overlap_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto overlap_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(polygon->touches(overlap_polygon.get()));
     }
     {
         const char* wkt = "MULTIPOLYGON(((10 0,20 0,20 10,10 10,10 0)))";
-        std::unique_ptr<GeoShape> touch_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto touch_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(polygon->touches(touch_polygon.get()));
     }
     {
         const char* wkt = "MULTIPOLYGON(((10.1 0,20 0,20 10,10.1 10,10.1 0)))";
-        std::unique_ptr<GeoShape> touch_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto touch_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(polygon->touches(touch_polygon.get()));
     }
     {
         const char* wkt = "MULTIPOLYGON(((9.99 0,20 0,20 10,9.99 10,9.99 0)))";
-        std::unique_ptr<GeoShape> touch_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto touch_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(polygon->touches(touch_polygon.get()));
     }
     {
         const char* wkt = "MULTIPOLYGON(((20 20,30 20,30 30,20 30,20 20)))";
-        std::unique_ptr<GeoShape> separate_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto separate_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(polygon->touches(separate_polygon.get()));
     }
 
     std::string buf;
     polygon->encode_to(&buf);
     {
-        std::unique_ptr<GeoShape> decoded(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto decoded = GeoShape::from_encoded(buf.data(), buf.size());
         ASSERT_NE(nullptr, decoded.get());
         EXPECT_EQ(GEO_SHAPE_POLYGON, decoded->type());
     }
     {
         buf.resize(buf.size() - 2);
-        std::unique_ptr<GeoShape> decoded(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto decoded = GeoShape::from_encoded(buf.data(), buf.size());
         EXPECT_EQ(nullptr, decoded.get());
     }
 }
@@ -1158,16 +1113,15 @@ TEST_F(GeoTypesTest, multipolygon_touches) {
     const char* test_line = "LINESTRING(10 5, 20 5)";
     const char* overlap_polygon = "POLYGON((8 8, 18 8, 18 18, 8 18, 8 8))";
     const char* test_multi_polygon =
-            "MULTIPOLYGON (((-5 -5, 0 -5, 0 0, -5 0, -5 -5)), ((40 40, 50 40, 
50 50, 40 50, 40 "
+            "MULTIPOLYGON (((-5 -5, 0 -5, 0 0, -5 0, -5 -5)), ((40 40, 50 40, 
50 50, 40 "
+            "50, 40 "
             "40)))";
 
-    std::unique_ptr<GeoShape> multipolygon(
-            GeoShape::from_wkt(base_multipolygon, strlen(base_multipolygon), 
&status));
-    std::unique_ptr<GeoShape> line(GeoShape::from_wkt(test_line, 
strlen(test_line), &status));
-    std::unique_ptr<GeoShape> other_polygon(
-            GeoShape::from_wkt(overlap_polygon, strlen(overlap_polygon), 
&status));
-    std::unique_ptr<GeoShape> other_multipolygon(
-            GeoShape::from_wkt(test_multi_polygon, strlen(test_multi_polygon), 
&status));
+    auto multipolygon(GeoShape::from_wkt(base_multipolygon, 
strlen(base_multipolygon), status));
+    auto line(GeoShape::from_wkt(test_line, strlen(test_line), status));
+    auto other_polygon(GeoShape::from_wkt(overlap_polygon, 
strlen(overlap_polygon), status));
+    auto other_multipolygon(
+            GeoShape::from_wkt(test_multi_polygon, strlen(test_multi_polygon), 
status));
     ASSERT_NE(nullptr, multipolygon.get());
     ASSERT_NE(nullptr, line.get());
     ASSERT_NE(nullptr, other_polygon.get());
@@ -1202,22 +1156,22 @@ TEST_F(GeoTypesTest, multipolygon_touches) {
     // ===========================
     {
         const char* wkt = "LINESTRING(3 5, 8 5)";
-        std::unique_ptr<GeoShape> in_hole_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto in_hole_line(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(multipolygon->touches(in_hole_line.get()));
     }
     {
         const char* wkt = "LINESTRING(10 5, 20 5)";
-        std::unique_ptr<GeoShape> cross_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto cross_line(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(multipolygon->touches(cross_line.get()));
     }
     {
         const char* wkt = "LINESTRING(30 30, 35 35)";
-        std::unique_ptr<GeoShape> edge_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto edge_line(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(multipolygon->touches(edge_line.get()));
     }
     {
         const char* wkt = "LINESTRING(10 10, 15 0)";
-        std::unique_ptr<GeoShape> cross_line(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto cross_line(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(multipolygon->touches(cross_line.get()));
     }
 
@@ -1226,37 +1180,37 @@ TEST_F(GeoTypesTest, multipolygon_touches) {
     // ========================
     {
         const char* wkt = "POLYGON((3 3, 8 3, 8 8, 3 8, 3 3))";
-        std::unique_ptr<GeoShape> in_hole_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto in_hole_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(multipolygon->touches(in_hole_polygon.get()));
     }
     {
         const char* wkt = "POLYGON((3 3, 10 3, 10 8, 3 8, 3 3))";
-        std::unique_ptr<GeoShape> cross_hole_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto cross_hole_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(multipolygon->touches(cross_hole_polygon.get()));
     }
     {
         const char* wkt = "POLYGON((25 0, 35 0, 35 10, 25 10, 25 0))";
-        std::unique_ptr<GeoShape> touch_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto touch_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(multipolygon->touches(touch_polygon.get()));
     }
     {
         const char* wkt = "POLYGON((8 8, 18 8, 18 18, 8 18, 8 8))";
-        std::unique_ptr<GeoShape> overlap_poly(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto overlap_poly(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(multipolygon->touches(overlap_poly.get()));
     }
     {
         const char* wkt = "POLYGON((10 0, 15 0, 15 10, 10 10, 10 0))";
-        std::unique_ptr<GeoShape> touch_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto touch_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(multipolygon->touches(touch_polygon.get()));
     }
     {
         const char* wkt = "POLYGON((20 20, 30 20, 30 30, 20 30, 20 20))";
-        std::unique_ptr<GeoShape> separate_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto separate_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(multipolygon->touches(separate_polygon.get()));
     }
     {
         const char* wkt = "POLYGON((10 0, 20 0, 20 5, 10 5, 10 0))";
-        std::unique_ptr<GeoShape> cross_polygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto cross_polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(multipolygon->touches(cross_polygon.get()));
     }
 
@@ -1265,22 +1219,25 @@ TEST_F(GeoTypesTest, multipolygon_touches) {
     // =============================
     {
         const char* wkt =
-                "MULTIPOLYGON (((-5 -5, 0 -5, 0 0, -5 0, -5 -5)), ((40 30, 50 
30, 50 50, 40 50, 40 "
+                "MULTIPOLYGON (((-5 -5, 0 -5, 0 0, -5 0, -5 -5)), ((40 30, 50 
30, 50 50, "
+                "40 "
+                "50, 40 "
                 "30)))";
-        std::unique_ptr<GeoShape> touch_multi(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto touch_multi(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(multipolygon->touches(touch_multi.get()));
     }
     {
         const char* wkt =
-                "MULTIPOLYGON (((8 8, 18 8, 18 18, 8 18, 8 8)), ((30 30, 40 
30, 35 25, 30 30)))";
-        std::unique_ptr<GeoShape> overlap_multi(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+                "MULTIPOLYGON (((8 8, 18 8, 18 18, 8 18, 8 8)), ((30 30, 40 
30, 35 25, 30 "
+                "30)))";
+        auto overlap_multi(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(multipolygon->touches(overlap_multi.get()));
     }
 
     std::string buf;
     multipolygon->encode_to(&buf);
     {
-        std::unique_ptr<GeoShape> decoded(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto decoded(GeoShape::from_encoded(buf.data(), buf.size()));
         ASSERT_NE(nullptr, decoded.get());
         EXPECT_EQ(GEO_SHAPE_MULTI_POLYGON, decoded->type());
 
@@ -1290,7 +1247,7 @@ TEST_F(GeoTypesTest, multipolygon_touches) {
     }
     {
         buf.resize(buf.size() - 2);
-        std::unique_ptr<GeoShape> decoded(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto decoded(GeoShape::from_encoded(buf.data(), buf.size()));
         EXPECT_EQ(nullptr, decoded.get());
     }
 }
@@ -1339,12 +1296,12 @@ TEST_F(GeoTypesTest, circle_touches) {
     // ======================
     {
         const char* wkt = "LINESTRING(-20 0, 20 0)";
-        std::unique_ptr<GeoShape> line(GeoShape::from_wkt(wkt, strlen(wkt), 
&status));
+        auto line(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(circle.touches(line.get()));
     }
     {
         const char* wkt = "LINESTRING(20 20, 30 30)";
-        std::unique_ptr<GeoShape> line(GeoShape::from_wkt(wkt, strlen(wkt), 
&status));
+        auto line(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(circle.touches(line.get()));
     }
 
@@ -1353,27 +1310,27 @@ TEST_F(GeoTypesTest, circle_touches) {
     // ======================
     {
         const char* wkt = "POLYGON((-5 -5,5 -5,5 5,-5 5,-5 -5))";
-        std::unique_ptr<GeoShape> poly(GeoShape::from_wkt(wkt, strlen(wkt), 
&status));
+        auto poly(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(circle.touches(poly.get()));
     }
     {
         const char* wkt = "POLYGON((10 0,20 0,20 10,10 10,10 0))";
-        std::unique_ptr<GeoShape> poly(GeoShape::from_wkt(wkt, strlen(wkt), 
&status));
+        auto poly(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(circle.touches(poly.get()));
     }
     {
         const char* wkt = "POLYGON((10.1 0,20 0,20 10,10.1 10,10.1 0))";
-        std::unique_ptr<GeoShape> poly(GeoShape::from_wkt(wkt, strlen(wkt), 
&status));
+        auto poly(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(circle.touches(poly.get()));
     }
     {
         const char* wkt = "POLYGON((9.99 0,20 0,20 10,9.99 10,9.99 0))";
-        std::unique_ptr<GeoShape> poly(GeoShape::from_wkt(wkt, strlen(wkt), 
&status));
+        auto poly(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_FALSE(circle.touches(poly.get()));
     }
     {
         const char* wkt = "POLYGON((-10 -10,10 -10,10 -20,-10 -20,-10 -10))";
-        std::unique_ptr<GeoShape> poly(GeoShape::from_wkt(wkt, strlen(wkt), 
&status));
+        auto poly(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_TRUE(circle.touches(poly.get()));
     }
 
@@ -1400,9 +1357,9 @@ TEST_F(GeoTypesTest, circle_touches) {
 }
 
 TEST_F(GeoTypesTest, polygon_contains) {
-    const char* wkt = "POLYGON ((10 10, 50 10, 50 10, 50 50, 50 50, 10 50, 10 
10))";
     GeoParseStatus status;
-    std::unique_ptr<GeoShape> polygon(GeoShape::from_wkt(wkt, strlen(wkt), 
&status));
+    const char* wkt = "POLYGON ((10 10, 50 10, 50 10, 50 50, 50 50, 10 50, 10 
10))";
+    auto polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
     EXPECT_NE(nullptr, polygon.get());
 
     {
@@ -1422,14 +1379,14 @@ TEST_F(GeoTypesTest, polygon_contains) {
     polygon->encode_to(&buf);
 
     {
-        std::unique_ptr<GeoShape> shape(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto shape(GeoShape::from_encoded(buf.data(), buf.size()));
         EXPECT_EQ(GEO_SHAPE_POLYGON, shape->type());
         LOG(INFO) << "polygon=" << shape->as_wkt();
     }
 
     {
         buf.resize(buf.size() - 1);
-        std::unique_ptr<GeoShape> shape(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto shape(GeoShape::from_encoded(buf.data(), buf.size()));
         EXPECT_EQ(nullptr, shape);
     }
 }
@@ -1438,21 +1395,21 @@ TEST_F(GeoTypesTest, polygon_parse_fail) {
     {
         const char* wkt = "POLYGON ((10 10, 50 10, 50 50, 10 50), (10 10 01))";
         GeoParseStatus status;
-        std::unique_ptr<GeoShape> polygon(GeoShape::from_wkt(wkt, strlen(wkt), 
&status));
+        auto polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_EQ(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;
-        std::unique_ptr<GeoShape> polygon(GeoShape::from_wkt(wkt, strlen(wkt), 
&status));
+        auto polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_EQ(GEO_PARSE_LOOP_NOT_CLOSED, status);
         EXPECT_EQ(nullptr, polygon.get());
     }
     {
         const char* wkt = "POLYGON ((10 10, 50 10, 10 10))";
         GeoParseStatus status;
-        std::unique_ptr<GeoShape> polygon(GeoShape::from_wkt(wkt, strlen(wkt), 
&status));
+        auto polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_EQ(GEO_PARSE_LOOP_LACK_VERTICES, status);
         EXPECT_EQ(nullptr, polygon.get());
     }
@@ -1460,9 +1417,10 @@ TEST_F(GeoTypesTest, polygon_parse_fail) {
 
 TEST_F(GeoTypesTest, polygon_hole_contains) {
     const char* wkt =
-            "POLYGON ((10 10, 50 10, 50 50, 10 50, 10 10), (20 20, 40 20, 40 
40, 20 40, 20 20))";
+            "POLYGON ((10 10, 50 10, 50 50, 10 50, 10 10), (20 20, 40 20, 40 
40, 20 40, 20 "
+            "20))";
     GeoParseStatus status;
-    std::unique_ptr<GeoShape> polygon(GeoShape::from_wkt(wkt, strlen(wkt), 
&status));
+    auto polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
     EXPECT_EQ(GEO_PARSE_OK, status);
     EXPECT_NE(nullptr, polygon);
 
@@ -1490,44 +1448,47 @@ TEST_F(GeoTypesTest, multipolygon_parse_fail) {
     {
         const char* wkt = "MULTIPOLYGON (((10 10, 50 10, 50 50, 10 50), (10 10 
01)))";
         GeoParseStatus status;
-        std::unique_ptr<GeoShape> multipolygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto multipolygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_EQ(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;
-        std::unique_ptr<GeoShape> multipolygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto multipolygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_EQ(GEO_PARSE_LOOP_NOT_CLOSED, status);
         EXPECT_EQ(nullptr, multipolygon.get());
     }
     {
         const char* wkt = "MULTIPOLYGON (((10 10, 50 10, 10 10)))";
         GeoParseStatus status;
-        std::unique_ptr<GeoShape> multipolygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto multipolygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_EQ(GEO_PARSE_LOOP_LACK_VERTICES, status);
         EXPECT_EQ(nullptr, multipolygon.get());
     }
     {
         const char* wkt =
-                "MULTIPOLYGON (((0 0, 0 10, 10 10, 10 0, 0 0)), ((5 5, 5 15, 
15 15, 15 5, 5 5)))";
+                "MULTIPOLYGON (((0 0, 0 10, 10 10, 10 0, 0 0)), ((5 5, 5 15, 
15 15, 15 5, "
+                "5 "
+                "5)))";
         GeoParseStatus status;
-        std::unique_ptr<GeoShape> multipolygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto multipolygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_EQ(GEO_PARSE_MULTIPOLYGON_OVERLAP, status);
         EXPECT_EQ(nullptr, multipolygon.get());
     }
     {
         const char* wkt =
-                "MULTIPOLYGON(((5 5, 5 8, 8 8, 8 5, 5 5)), ((8 6, 10 6, 10 10, 
8 10, 8 6)))";
+                "MULTIPOLYGON(((5 5, 5 8, 8 8, 8 5, 5 5)), ((8 6, 10 6, 10 10, 
8 10, 8 "
+                "6)))";
         GeoParseStatus status;
-        std::unique_ptr<GeoShape> multipolygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto multipolygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_EQ(GEO_PARSE_MULTIPOLYGON_OVERLAP, status);
         EXPECT_EQ(nullptr, multipolygon.get());
     }
     {
         const char* wkt = "MULTIPOLYGON((()))";
         GeoParseStatus status;
-        std::unique_ptr<GeoShape> multipolygon(GeoShape::from_wkt(wkt, 
strlen(wkt), &status));
+        auto multipolygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
         EXPECT_EQ(GEO_PARSE_WKT_SYNTAX_ERROR, status);
         EXPECT_EQ(nullptr, multipolygon.get());
     }
@@ -1542,13 +1503,13 @@ TEST_F(GeoTypesTest, circle) {
     circle.encode_to(&buf);
 
     {
-        std::unique_ptr<GeoShape> circle2(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto circle2(GeoShape::from_encoded(buf.data(), buf.size()));
         EXPECT_STREQ("CIRCLE ((110.123 64), 1000)", circle2->as_wkt().c_str());
     }
 
     {
         buf.resize(buf.size() - 1);
-        std::unique_ptr<GeoShape> circle2(GeoShape::from_encoded(buf.data(), 
buf.size()));
+        auto circle2(GeoShape::from_encoded(buf.data(), buf.size()));
         EXPECT_EQ(nullptr, circle2);
     }
 }
diff --git a/be/test/geo/wkb_parse_test.cpp b/be/test/geo/wkb_parse_test.cpp
new file mode 100644
index 00000000000..64dc70781a4
--- /dev/null
+++ b/be/test/geo/wkb_parse_test.cpp
@@ -0,0 +1,179 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "geo/wkb_parse.h"
+
+#include <gtest/gtest.h>
+
+#include <memory>
+#include <sstream>
+#include <string>
+
+#include "geo/geo_types.h"
+
+namespace doris {
+
+class WkbParseTest : public ::testing::Test {
+public:
+    WkbParseTest() = default;
+    ~WkbParseTest() override = default;
+};
+
+TEST_F(WkbParseTest, parse_point_little_endian_ndr) {
+    std::string hex_wkb = "0101000000000000000000F03F0000000000000040";
+    std::stringstream ss(hex_wkb);
+
+    std::unique_ptr<GeoShape> shape;
+    auto status = WkbParse::parse_wkb(ss, shape);
+
+    EXPECT_EQ(GEO_PARSE_OK, status);
+    ASSERT_NE(nullptr, shape);
+    EXPECT_EQ(GEO_SHAPE_POINT, shape->type());
+    EXPECT_STREQ("POINT (1 2)", shape->as_wkt().c_str());
+}
+
+TEST_F(WkbParseTest, parse_point_big_endian_xdr) {
+    std::string hex_wkb = "00000000013FF00000000000004000000000000000";
+    std::stringstream ss(hex_wkb);
+
+    std::unique_ptr<GeoShape> shape;
+    auto status = WkbParse::parse_wkb(ss, shape);
+
+    EXPECT_EQ(GEO_PARSE_OK, status);
+    ASSERT_NE(nullptr, shape);
+    EXPECT_EQ(GEO_SHAPE_POINT, shape->type());
+    EXPECT_STREQ("POINT (1 2)", shape->as_wkt().c_str());
+}
+
+TEST_F(WkbParseTest, parse_invalid_byte_order_ff) {
+    std::string hex_wkb = "FF01000000000000000000F03F0000000000000040";
+    std::stringstream ss(hex_wkb);
+
+    std::unique_ptr<GeoShape> shape;
+    auto status = WkbParse::parse_wkb(ss, shape);
+
+    EXPECT_EQ(GEO_PARSE_WKB_SYNTAX_ERROR, status);
+    EXPECT_EQ(nullptr, shape);
+}
+
+TEST_F(WkbParseTest, parse_invalid_byte_order_02) {
+    std::string hex_wkb = "0201000000000000000000F03F0000000000000040";
+    std::stringstream ss(hex_wkb);
+
+    std::unique_ptr<GeoShape> shape;
+    auto status = WkbParse::parse_wkb(ss, shape);
+
+    EXPECT_EQ(GEO_PARSE_WKB_SYNTAX_ERROR, status);
+    EXPECT_EQ(nullptr, shape);
+}
+
+TEST_F(WkbParseTest, parse_empty_stream) {
+    std::stringstream ss;
+
+    std::unique_ptr<GeoShape> shape;
+    auto status = WkbParse::parse_wkb(ss, shape);
+
+    EXPECT_EQ(GEO_PARSE_WKB_SYNTAX_ERROR, status);
+    EXPECT_EQ(nullptr, shape);
+}
+
+TEST_F(WkbParseTest, parse_insufficient_data) {
+    std::string hex_wkb = "01";
+    std::stringstream ss(hex_wkb);
+
+    std::unique_ptr<GeoShape> shape;
+    auto status = WkbParse::parse_wkb(ss, shape);
+
+    EXPECT_EQ(GEO_PARSE_WKB_SYNTAX_ERROR, status);
+    EXPECT_EQ(nullptr, shape);
+}
+
+TEST_F(WkbParseTest, parse_odd_length_hex) {
+    std::string hex_wkb = "010100000000000000000F03F0000000000000040";
+    std::stringstream ss(hex_wkb);
+
+    std::unique_ptr<GeoShape> shape;
+    auto status = WkbParse::parse_wkb(ss, shape);
+
+    EXPECT_EQ(GEO_PARSE_WKB_SYNTAX_ERROR, status);
+    EXPECT_EQ(nullptr, shape);
+}
+
+TEST_F(WkbParseTest, parse_linestring_little_endian) {
+    std::string hex_wkb =
+            
"010200000002000000000000000000F03F00000000000000400000000000000840000000000000F03F";
+    std::stringstream ss(hex_wkb);
+
+    std::unique_ptr<GeoShape> shape;
+    auto status = WkbParse::parse_wkb(ss, shape);
+
+    EXPECT_EQ(GEO_PARSE_OK, status);
+    ASSERT_NE(nullptr, shape);
+}
+
+TEST_F(WkbParseTest, test_byte_order_coverage_multiple_invalid) {
+    std::vector<std::string> invalid_prefixes = {"FF", "02", "AA", "80", "FE"};
+
+    for (const auto& prefix : invalid_prefixes) {
+        std::string hex_wkb = prefix + 
"01000000000000000000F03F0000000000000040";
+        std::stringstream ss(hex_wkb);
+
+        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(nullptr, shape) << "Failed for byte order prefix: " << 
prefix;
+    }
+}
+
+TEST_F(WkbParseTest, parse_unsupported_geometry_type) {
+    std::string hex_wkb = "0104000000000000000000F03F0000000000000040";
+    std::stringstream ss(hex_wkb);
+
+    std::unique_ptr<GeoShape> shape;
+    auto status = WkbParse::parse_wkb(ss, shape);
+
+    EXPECT_EQ(GEO_PARSE_WKB_SYNTAX_ERROR, status);
+    EXPECT_EQ(nullptr, shape);
+}
+
+TEST_F(WkbParseTest, parse_geometry_with_srid) {
+    std::string hex_wkb = "0101000020E6100000000000000000F03F0000000000000040";
+    std::stringstream ss(hex_wkb);
+
+    std::unique_ptr<GeoShape> shape;
+    auto status = WkbParse::parse_wkb(ss, shape);
+
+    EXPECT_EQ(GEO_PARSE_OK, status);
+    ASSERT_NE(nullptr, shape);
+    EXPECT_EQ(GEO_SHAPE_POINT, shape->type());
+}
+
+TEST_F(WkbParseTest, parse_polygon_insufficient_points) {
+    std::string hex_wkb =
+            
"01030000000100000002000000000000000000000000000000000000000000000000001440000000000000"
+            "0000";
+    std::stringstream ss(hex_wkb);
+
+    std::unique_ptr<GeoShape> shape;
+    auto status = WkbParse::parse_wkb(ss, shape);
+
+    EXPECT_EQ(GEO_PARSE_WKB_SYNTAX_ERROR, status);
+    EXPECT_EQ(nullptr, shape);
+}
+
+} // namespace doris
\ No newline at end of file
diff --git a/be/test/geo/wkt_parse_test.cpp b/be/test/geo/wkt_parse_test.cpp
index 8a50428f122..721a646c5d9 100644
--- a/be/test/geo/wkt_parse_test.cpp
+++ b/be/test/geo/wkt_parse_test.cpp
@@ -21,6 +21,7 @@
 #include <gtest/gtest-test-part.h>
 #include <string.h>
 
+#include <memory>
 #include <ostream>
 #include <string>
 
@@ -39,19 +40,18 @@ public:
 TEST_F(WktParseTest, normal) {
     const char* wkt = "POINT(1 2)";
 
-    GeoShape* shape = nullptr;
-    auto status = WktParse::parse_wkt(wkt, strlen(wkt), &shape);
+    std::unique_ptr<GeoShape> shape;
+    auto status = WktParse::parse_wkt(wkt, strlen(wkt), shape);
     EXPECT_EQ(GEO_PARSE_OK, status);
     EXPECT_NE(nullptr, shape);
     LOG(INFO) << "parse result: " << shape->to_string();
-    delete shape;
 }
 
 TEST_F(WktParseTest, invalid_wkt) {
     const char* wkt = "POINT(1,2)";
 
-    GeoShape* shape = nullptr;
-    auto status = WktParse::parse_wkt(wkt, strlen(wkt), &shape);
+    std::unique_ptr<GeoShape> shape;
+    auto status = WktParse::parse_wkt(wkt, strlen(wkt), shape);
     EXPECT_NE(GEO_PARSE_OK, status);
     EXPECT_EQ(nullptr, shape);
 }
diff --git a/be/test/vec/function/function_geo_test.cpp 
b/be/test/vec/function/function_geo_test.cpp
index 16828d4f42d..ff35035f5a4 100644
--- a/be/test/vec/function/function_geo_test.cpp
+++ b/be/test/vec/function/function_geo_test.cpp
@@ -271,7 +271,7 @@ TEST(VGeoFunctionsTest, function_geo_st_contains) {
     GeoParseStatus status;
 
     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));
+    std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(shape1.data(), 
shape1.size(), status));
     EXPECT_TRUE(status == GEO_PARSE_OK);
     EXPECT_TRUE(shape != nullptr);
     shape->encode_to(&buf1);
@@ -345,7 +345,7 @@ TEST(VGeoFunctionsTest, function_geo_st_geometryfromtext) {
         GeoParseStatus status;
         std::string buf;
         std::string input = "LINESTRING (1 1, 2 2)";
-        std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(input.data(), 
input.size(), &status));
+        std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(input.data(), 
input.size(), status));
         EXPECT_TRUE(shape != nullptr);
         EXPECT_TRUE(status == GEO_PARSE_OK);
         shape->encode_to(&buf);
@@ -363,7 +363,7 @@ TEST(VGeoFunctionsTest, function_geo_st_geomfromtext) {
         GeoParseStatus status;
         std::string buf;
         std::string input = "LINESTRING (1 1, 2 2)";
-        std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(input.data(), 
input.size(), &status));
+        std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(input.data(), 
input.size(), status));
         EXPECT_TRUE(shape != nullptr);
         EXPECT_TRUE(status == GEO_PARSE_OK);
         shape->encode_to(&buf);
@@ -381,7 +381,7 @@ TEST(VGeoFunctionsTest, function_geo_st_linefromtext) {
         GeoParseStatus status;
         std::string buf;
         std::string input = "LINESTRING (1 1, 2 2)";
-        std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(input.data(), 
input.size(), &status));
+        std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(input.data(), 
input.size(), status));
         EXPECT_TRUE(shape != nullptr);
         EXPECT_TRUE(status == GEO_PARSE_OK);
         shape->encode_to(&buf);
@@ -399,7 +399,7 @@ TEST(VGeoFunctionsTest, function_geo_st_polygon) {
         GeoParseStatus status;
         std::string buf;
         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));
+        std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(input.data(), 
input.size(), status));
         EXPECT_TRUE(shape != nullptr);
         EXPECT_TRUE(status == GEO_PARSE_OK);
         shape->encode_to(&buf);
@@ -418,7 +418,7 @@ TEST(VGeoFunctionsTest, function_geo_st_polygonfromtext) {
         GeoParseStatus status;
         std::string buf;
         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));
+        std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(input.data(), 
input.size(), status));
         EXPECT_TRUE(shape != nullptr);
         EXPECT_TRUE(status == GEO_PARSE_OK);
         shape->encode_to(&buf);
@@ -453,7 +453,7 @@ TEST(VGeoFunctionsTest, function_geo_st_area_square_km) {
         GeoParseStatus status;
         std::string buf;
         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));
+        std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(input.data(), 
input.size(), status));
         EXPECT_TRUE(shape != nullptr);
         EXPECT_TRUE(status == GEO_PARSE_OK);
         shape->encode_to(&buf);


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

Reply via email to