diff --git a/deps/oblib/src/lib/geo/ob_geo_utils.cpp b/deps/oblib/src/lib/geo/ob_geo_utils.cpp index 485a7e574..230cdd600 100644 --- a/deps/oblib/src/lib/geo/ob_geo_utils.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_utils.cpp @@ -650,6 +650,23 @@ int ObGeoTypeUtil::get_bo_from_wkb(const ObString &wkb, ObGeoWkbByteOrder &bo) return ret; } +int ObGeoTypeUtil::add_geo_version(ObIAllocator &allocator, const ObString &src, ObString &res_wkb) +{ + int ret = OB_SUCCESS; + uint64_t res_size = src.length() + WKB_VERSION_SIZE; + char *res_buf = reinterpret_cast(allocator.alloc(res_size)); + if (OB_ISNULL(res_buf)) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to alloc memory", K(ret), K(res_size)); + } else { + MEMCPY(res_buf, src.ptr(), WKB_GEO_SRID_SIZE); + *(res_buf + WKB_GEO_SRID_SIZE) = ENCODE_GEO_VERSION(GEO_VESION_1); + MEMCPY(res_buf + WKB_OFFSET, src.ptr() + WKB_GEO_SRID_SIZE, src.length() - WKB_GEO_SRID_SIZE); + res_wkb.assign_ptr(res_buf, res_size); + } + return ret; +} + int ObGeoTypeUtil::to_wkb(ObIAllocator &allocator, ObGeometry &geo, const ObSrsItem *srs_item, diff --git a/deps/oblib/src/lib/geo/ob_geo_utils.h b/deps/oblib/src/lib/geo/ob_geo_utils.h index 0ea44c5cb..ed22e862a 100644 --- a/deps/oblib/src/lib/geo/ob_geo_utils.h +++ b/deps/oblib/src/lib/geo/ob_geo_utils.h @@ -119,6 +119,7 @@ public: ObS2Cellids &cellids, ObString &mbr_val); static int get_wkb_from_swkb(const ObString &swkb, ObString &wkb, uint32_t &offset); + static int add_geo_version(ObIAllocator &allocator, const ObString &src, ObString &res_wkb); private: template static int create_geo_bin_by_type(ObIAllocator &allocator, diff --git a/deps/oblib/src/rpc/obmysql/ob_mysql_util.cpp b/deps/oblib/src/rpc/obmysql/ob_mysql_util.cpp index b2a29d625..9d8bad035 100644 --- a/deps/oblib/src/rpc/obmysql/ob_mysql_util.cpp +++ b/deps/oblib/src/rpc/obmysql/ob_mysql_util.cpp @@ -1223,7 +1223,14 @@ int ObMySQLUtil::geometry_cell_str(char *buf, const int64_t len, const ObString ret = OB_SIZE_OVERFLOW; } } else { - length = val.length() - WKB_VERSION_SIZE; + uint8_t version = (*(val.ptr() + WKB_GEO_SRID_SIZE)); + uint8_t offset = WKB_GEO_SRID_SIZE; + if (IS_GEO_VERSION(version)) { + // version exist + length = val.length() - WKB_VERSION_SIZE; + offset += WKB_VERSION_SIZE; + } + if (OB_LIKELY(length < len - pos)) { int64_t pos_bk = pos; if (OB_FAIL(ObMySQLUtil::store_length(buf, len, length, pos))) { @@ -1232,7 +1239,7 @@ int ObMySQLUtil::geometry_cell_str(char *buf, const int64_t len, const ObString if (OB_LIKELY(length <= len - pos)) { MEMCPY(buf + pos, val.ptr(), WKB_GEO_SRID_SIZE); // srid pos += WKB_GEO_SRID_SIZE; - MEMCPY(buf + pos, val.ptr() + WKB_OFFSET, length - WKB_GEO_SRID_SIZE); + MEMCPY(buf + pos, val.ptr() + offset, length - WKB_GEO_SRID_SIZE); pos += (length - WKB_GEO_SRID_SIZE); } else { pos = pos_bk; diff --git a/src/share/object/ob_obj_cast.cpp b/src/share/object/ob_obj_cast.cpp index d56a8c1f7..283a90f4a 100644 --- a/src/share/object/ob_obj_cast.cpp +++ b/src/share/object/ob_obj_cast.cpp @@ -6322,8 +6322,13 @@ static int string_geometry(const ObObjType expect_type, ObObjCastParams ¶ms, } else if (OB_FAIL(common_build_geometry(temp_allocator, in_str, geo, srs, cast_name))) { LOG_WARN("fail to parse geometry", K(ret), K(in_str), K(dst_geo_type)); } else if (ObGeoType::GEOMETRY == dst_geo_type) { - out.set_string(expect_type, in_str.ptr(), in_str.length()); - SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, in_str.length()); + ObString res_wkb; + if (OB_FAIL(ObGeoTypeUtil::add_geo_version(temp_allocator, in_str, res_wkb))) { + LOG_WARN("fail to add version", K(ret), K(dst_geo_type)); + } else { + out.set_string(expect_type, res_wkb.ptr(), res_wkb.length()); + SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_wkb.length()); + } } else if (OB_FAIL(geometry_geometry(expect_type, params, in, out, cast_mode))) { LOG_WARN("fail to cast geometry", K(ret), K(dst_geo_type)); } @@ -9089,14 +9094,21 @@ static int geom_copy_string(ObObjCastParams ¶ms, { int ret = OB_SUCCESS; char *buf = NULL; - int64_t len = src.length() - WKB_VERSION_SIZE; - if (OB_LIKELY(len > 0)) { + int64_t len = src.length(); + uint8_t offset = WKB_GEO_SRID_SIZE; + if (OB_LIKELY(len > WKB_OFFSET)) { + uint8_t version = (*(src.ptr() + WKB_GEO_SRID_SIZE)); + if (IS_GEO_VERSION(version)) { + // version exist + len -= WKB_VERSION_SIZE; + offset += WKB_VERSION_SIZE; + } if (is_lob_storage(expect_type)) { bool has_lob_header = (!IS_CLUSTER_VERSION_BEFORE_4_1_0_0 && (expect_type != ObTinyTextType)); sql::ObTextStringObObjResult str_result(expect_type, ¶ms, &obj, has_lob_header); if (OB_FAIL(str_result.init(len))) { } else if (OB_FAIL(str_result.append(src.ptr(), WKB_GEO_SRID_SIZE))) { - } else if (OB_FAIL(str_result.append(src.ptr() + WKB_OFFSET, len - WKB_GEO_SRID_SIZE))) { + } else if (OB_FAIL(str_result.append(src.ptr() + offset, len - WKB_GEO_SRID_SIZE))) { } else { str_result.set_result(); } @@ -9105,7 +9117,7 @@ static int geom_copy_string(ObObjCastParams ¶ms, ret = OB_ALLOCATE_MEMORY_FAILED; } else { MEMMOVE(buf, src.ptr(), WKB_GEO_SRID_SIZE); - MEMMOVE(buf + WKB_GEO_SRID_SIZE, src.ptr() + WKB_OFFSET, len - WKB_GEO_SRID_SIZE); + MEMMOVE(buf + WKB_GEO_SRID_SIZE, src.ptr() + offset, len - WKB_GEO_SRID_SIZE); if (ob_is_raw(expect_type)) { obj.set_raw(buf, static_cast(len)); } else { diff --git a/src/sql/engine/expr/ob_datum_cast.cpp b/src/sql/engine/expr/ob_datum_cast.cpp index 75582dfb0..2cdad7f2f 100644 --- a/src/sql/engine/expr/ob_datum_cast.cpp +++ b/src/sql/engine/expr/ob_datum_cast.cpp @@ -526,15 +526,23 @@ static int common_json_bin(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datu return ret; } -static int common_gis_wkb(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum, ObString &wkb) +static int common_gis_wkb(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum, ObString &wkb, bool skip_ver = false) { int ret = OB_SUCCESS; ObTextStringDatumResult text_result(ObGeometryType, &expr, &ctx, &res_datum); - if (OB_FAIL(text_result.init(wkb.length()))) { + uint32_t len = skip_ver ? wkb.length() - WKB_VERSION_SIZE : wkb.length(); + if (OB_FAIL(text_result.init(len))) { LOG_WARN("Lob: init lob result failed"); + } else if (skip_ver) { + if (OB_FAIL(text_result.append(wkb.ptr(), WKB_GEO_SRID_SIZE))) { + LOG_WARN("failed to append realdata", K(ret), K(wkb), K(text_result)); + } else if (OB_FAIL(text_result.append(wkb.ptr() + WKB_OFFSET, len - WKB_GEO_SRID_SIZE))) { + LOG_WARN("failed to append realdata", K(ret), K(wkb), K(text_result)); + } } else if (OB_FAIL(text_result.append(wkb.ptr(), wkb.length()))) { LOG_WARN("failed to append realdata", K(ret), K(wkb), K(text_result)); - } else { + } + if (OB_SUCC(ret)) { text_result.set_result(); } return ret; @@ -4017,7 +4025,10 @@ CAST_FUNC_NAME(string, geometry) } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, in_str, geo, srs, cast_name))) { LOG_WARN("fail to parse geometry", K(ret), K(in_str), K(dst_geo_type)); } else if (ObGeoType::GEOMETRY == dst_geo_type || ObGeoType::GEOTYPEMAX == dst_geo_type) { - if (OB_FAIL(common_gis_wkb(expr, ctx, res_datum, in_str))){ + ObString res_wkb; + if (OB_FAIL(ObGeoTypeUtil::add_geo_version(temp_allocator, in_str, res_wkb))) { + LOG_WARN("fail to add version", K(ret), K(dst_geo_type)); + } else if (OB_FAIL(common_gis_wkb(expr, ctx, res_datum, res_wkb))) { LOG_WARN("fail to copy string", K(ret), K(dst_geo_type)); } } else if (OB_FAIL(geometry_geometry(expr, ctx, res_datum))) { @@ -8576,26 +8587,38 @@ static int geom_copy_string(const ObExpr &expr, { int ret = OB_SUCCESS; char *out_ptr = NULL; - int64_t len = src.length() - WKB_VERSION_SIZE; - if (expr.obj_meta_.is_lob_storage()) { - if (OB_FAIL(common_gis_wkb(expr, ctx, res_datum, src))) { - LOG_WARN("fail to pack gis lob res", K(ret)); + int64_t len = src.length(); + if (OB_LIKELY(len > WKB_OFFSET)) { + uint8_t offset = WKB_GEO_SRID_SIZE; + uint8_t version = (*(src.ptr() + WKB_GEO_SRID_SIZE)); + if (IS_GEO_VERSION(version)) { + // version exist + len -= WKB_VERSION_SIZE; + offset += WKB_VERSION_SIZE; } - } else { - if (expr.res_buf_len_ < len) { - if (OB_ISNULL(out_ptr = expr.get_str_res_mem(ctx, len))) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_WARN("allocate memory failed", K(ret)); + if (expr.obj_meta_.is_lob_storage()) { + if (OB_FAIL(common_gis_wkb(expr, ctx, res_datum, src, IS_GEO_VERSION(version)))) { + LOG_WARN("fail to pack gis lob res", K(ret)); } } else { - out_ptr = const_cast(res_datum.ptr_); - } + if (expr.res_buf_len_ < len) { + if (OB_ISNULL(out_ptr = expr.get_str_res_mem(ctx, len))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("allocate memory failed", K(ret)); + } + } else { + out_ptr = const_cast(res_datum.ptr_); + } - if (OB_SUCC(ret)) { - MEMMOVE(out_ptr, src.ptr(), WKB_GEO_SRID_SIZE); - MEMMOVE(out_ptr + WKB_GEO_SRID_SIZE, src.ptr() + WKB_OFFSET, len - WKB_GEO_SRID_SIZE); - res_datum.set_string(out_ptr, len); + if (OB_SUCC(ret)) { + MEMMOVE(out_ptr, src.ptr(), WKB_GEO_SRID_SIZE); + MEMMOVE(out_ptr + WKB_GEO_SRID_SIZE, src.ptr() + offset, len - WKB_GEO_SRID_SIZE); + res_datum.set_string(out_ptr, len); + } } + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid obj len", K(ret), K(len)); } return ret; }