diff --git a/README.md b/README.md index 16f067ef6..c77087278 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ obd demo docker exec -it oceanbase-ce obclient -h127.0.0.1 -P2881 -uroot # Connect to the root user of the sys tenant. ``` -See also [Docker Readme](https://github.com/oceanbase/docker-images/tree/main/oceanbase-ce) for more details. +See also [Docker Readme](https://github.com/oceanbase/docker-images/blob/main/oceanbase-ce/README.md) for more details. ## ☸️ Start with Kubernetes diff --git a/README_CN.md b/README_CN.md index 34b5aa65a..fb1568de4 100644 --- a/README_CN.md +++ b/README_CN.md @@ -91,7 +91,7 @@ obd demo docker exec -it oceanbase-ce obclient -h127.0.0.1 -P2881 -uroot # 连接root用户sys租户 ``` -更多信息参考[docker 文档](https://github.com/oceanbase/docker-images/tree/main/oceanbase-ce)。 +更多信息参考[docker 文档](https://github.com/oceanbase/docker-images/blob/main/oceanbase-ce/README_CN.md)。 ## ☸️ 使用 Kubernetes diff --git a/cmake/Env.cmake b/cmake/Env.cmake index cbf522d3e..b05ff589d 100644 --- a/cmake/Env.cmake +++ b/cmake/Env.cmake @@ -35,7 +35,7 @@ ob_define(ENABLE_PERF_MODE OFF) # begin of unity build config ob_define(OB_MAX_UNITY_BATCH_SIZE 30) -# the global switch of unity build, defualt is 'ON' +# the global switch of unity build, default is 'ON' ob_define(OB_ENABLE_UNITY ON) ob_define(OB_BUILD_OPENSOURCE ON) @@ -48,7 +48,7 @@ ob_define(OB_DISABLE_PIE OFF) if(WITH_COVERAGE) # -ftest-coverage to generate .gcno file # -fprofile-arcs to generate .gcda file - # -DDBUILD_COVERAGE marco use to mark 'coverage build type' and to handle some speical case + # -DDBUILD_COVERAGE marco use to mark 'coverage build type' and to handle some special case set(CMAKE_COVERAGE_COMPILE_OPTIONS -ftest-coverage -fprofile-arcs -Xclang -coverage-version=408R -DBUILD_COVERAGE) set(CMAKE_COVERAGE_EXE_LINKER_OPTIONS "-ftest-coverage -fprofile-arcs") @@ -114,7 +114,7 @@ if(OB_BUILD_CLOSE_MODULES) # share storage ob_define(OB_BUILD_SHARED_STORAGE ON) - # oralce + # oracle ob_define(OB_BUILD_ORACLE_PARSER ON) ob_define(OB_BUILD_ORACLE_PL ON) # dblink diff --git a/deps/init/dep_create.sh b/deps/init/dep_create.sh index 3b69b1743..4c7e97291 100644 --- a/deps/init/dep_create.sh +++ b/deps/init/dep_create.sh @@ -58,6 +58,11 @@ function echo_err() { function get_os_release() { if [[ "${OS_ARCH}x" == "x86_64x" ]]; then case "$ID" in + rhel) + version_ge "9.0" && compat_centos9 && return + version_ge "8.0" && compat_centos8 && return + version_ge "7.0" && compat_centos7 && return + ;; alinux) version_ge "3.0" && compat_alinux3 && return version_ge "2.1903" && compat_centos7 && return @@ -118,6 +123,11 @@ function get_os_release() { esac elif [[ "${OS_ARCH}x" == "aarch64x" ]]; then case "$ID" in + rhel) + version_ge "9.0" && compat_centos9 && return + version_ge "8.0" && compat_centos8 && return + version_ge "7.0" && compat_centos7 && return + ;; alios) version_ge "8.0" && compat_centos8 && return version_ge "7.0" && compat_centos7 && return diff --git a/deps/oblib/src/lib/function/ob_function.h b/deps/oblib/src/lib/function/ob_function.h index 4decf5919..a328126b1 100644 --- a/deps/oblib/src/lib/function/ob_function.h +++ b/deps/oblib/src/lib/function/ob_function.h @@ -67,7 +67,7 @@ * call stored callable object, make sure ObFunction is valid before call this. * * - CAUTION: - * + DO check is_valid() after ObFuntion contructed, cause store big callable object may alloc + * + DO check is_valid() after ObFunction constructed, cause store big callable object may alloc * memory, set ObFunction to a invalid state if alloc memory failed. * + MAKE SURE ObFunction is valid before call it, or will CRASH. * @@ -234,7 +234,7 @@ public: } // normal constructor // ObFunction is a callable class also, so enable_if(SFINAE) condition is needed here, - // to making ObFunction copy and move constructor avaliable + // to making ObFunction copy and move constructor available template ::type, ObFunction>::value && @@ -312,7 +312,7 @@ public: int ret = OB_SUCCESS; if ((&allocator_ == &rhs.allocator_) && !is_local_obj_() && !rhs.is_local_obj_()) { // same allocator, both self and rhs are big obj - // just swap pointer, rhs will destory and destruct this->base_ + // just swap pointer, rhs will destroy and destruct this->base_ Abstract *temp = base_; base_ = rhs.base_; rhs.base_ = temp; diff --git a/deps/oblib/src/lib/future/ob_future.h b/deps/oblib/src/lib/future/ob_future.h index 734aa3391..f8aef26e3 100644 --- a/deps/oblib/src/lib/future/ob_future.h +++ b/deps/oblib/src/lib/future/ob_future.h @@ -281,7 +281,7 @@ protected: CHECK_INITED(); int ret = OB_SUCCESS; if (OB_FAIL(ObFutureBaseBase::wait())) { - OCCAM_LOG(WARN, "something wrong happend while waiting", K(ret)); + OCCAM_LOG(WARN, "something wrong happened while waiting", K(ret)); } else { ptr = &(data_shared_ptr_->data_); } @@ -400,7 +400,7 @@ protected: CHECK_INITED(); int ret = OB_SUCCESS; if (OB_FAIL(ObFutureBaseBase::wait())) { - OCCAM_LOG(WARN, "something wrong happend while waiting", K(ret)); + OCCAM_LOG(WARN, "something wrong happened while waiting", K(ret)); } return ret; } diff --git a/deps/oblib/src/lib/geo/ob_geo_cache_polygon.cpp b/deps/oblib/src/lib/geo/ob_geo_cache_polygon.cpp index c1414ae3c..d7fa2d6ce 100644 --- a/deps/oblib/src/lib/geo/ob_geo_cache_polygon.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_cache_polygon.cpp @@ -505,7 +505,7 @@ int ObCachedGeoPolygon::inner_eval_contains(ObGeometry& geo, ObGeoEvalCtx& gis_c return ret; } -// check if CachedPolygon catains geo +// check if CachedPolygon contains geo int ObCachedGeoPolygon::contains(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res) { int ret = OB_SUCCESS; @@ -530,7 +530,7 @@ int ObCachedGeoPolygon::contains(ObGeometry& geo, ObGeoEvalCtx& gis_context, boo return ret; } -// check if CachedPolygon catains geo +// check if CachedPolygon contains geo int ObCachedGeoPolygon::cover(ObGeometry& geo, ObGeoEvalCtx& gis_context, bool &res) { int ret = OB_SUCCESS; diff --git a/deps/oblib/src/lib/geo/ob_geo_func_transform.cpp b/deps/oblib/src/lib/geo/ob_geo_func_transform.cpp index 7b9e489f9..820d26ab6 100644 --- a/deps/oblib/src/lib/geo/ob_geo_func_transform.cpp +++ b/deps/oblib/src/lib/geo/ob_geo_func_transform.cpp @@ -76,7 +76,7 @@ private: common::ObIAllocator *alloc = context.get_allocator(); if (OB_ISNULL(alloc)) { ret = OB_ERR_NULL_VALUE; - LOG_WARN("unexpected null alloactor for transform functor", K(ret)); + LOG_WARN("unexpected null allocator for transform functor", K(ret)); } else if (OB_ISNULL(dest_geo = OB_NEWx(GeometryResType, alloc))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to create geo by type", K(ret)); @@ -104,7 +104,7 @@ private: common::ObIAllocator *alloc = context.get_allocator(); if (OB_ISNULL(alloc)) { ret = OB_ERR_NULL_VALUE; - LOG_WARN("unexpected null alloactor for transform functor", K(ret)); + LOG_WARN("unexpected null allocator for transform functor", K(ret)); } else if (OB_ISNULL(dest_geo = OB_NEWx(GCOutType, alloc, 0, *alloc))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to create geometry collection", K(ret)); diff --git a/docs/docs/en/build-and-run.md b/docs/docs/en/build-and-run.md index 599f75285..e94f46a0b 100644 --- a/docs/docs/en/build-and-run.md +++ b/docs/docs/en/build-and-run.md @@ -37,7 +37,7 @@ Now that you built the `observer` binary, you can deploy an OceanBase instance w ./tools/deploy/obd.sh deploy -c ./tools/deploy/single.yaml ``` -This starts the OceanBase server listening on port 10000. +You can check the `mysql_port` in `./tools/deploy/single.yaml` file to see the listening port. Normally, if you deploy with the root user, the OceanBase server will listen on port 10000, and the examples below are also based on this port. ## Connect diff --git a/docs/docs/zh/build-and-run.md b/docs/docs/zh/build-and-run.md index 788d1505c..1c7a04a6c 100644 --- a/docs/docs/zh/build-and-run.md +++ b/docs/docs/zh/build-and-run.md @@ -36,8 +36,7 @@ bash build.sh release --init --make ./tools/deploy/obd.sh prepare -p /tmp/obtest ./tools/deploy/obd.sh deploy -c ./tools/deploy/single.yaml ``` - -OceanBase 服务程序会监听 10000 端口。 +你可以通过查看 `./tools/deploy/single.yaml` 文件中的`mysql_port`来查看监听端口,通常情况下,如果你用root用户部署,那么OceanBase 服务程序会监听 10000 端口,下文中的示例也是基于这个端口。 ## 连接 diff --git a/src/logservice/logminer/ob_log_miner_record.cpp b/src/logservice/logminer/ob_log_miner_record.cpp index 87b41e225..7fc567e06 100644 --- a/src/logservice/logminer/ob_log_miner_record.cpp +++ b/src/logservice/logminer/ob_log_miner_record.cpp @@ -441,24 +441,25 @@ int ObLogMinerRecord::build_dml_stmt_(ICDCRecord &cdc_rec) binlogBuf *new_cols = cdc_rec.newCols(new_col_cnt); binlogBuf *old_cols = cdc_rec.oldCols(old_col_cnt); ITableMeta *tbl_meta = cdc_rec.getTableMeta(); - // When updating or deleting records with lob type, - // the null value of the lob type column may be incorrect - // due to the limitations of obcdc. - bool has_lob_null = false; - // xmltype and sdo_geometry type don't support compare operation. + // When updating or deleting records with value null, + // the null value of the column may be incorrect + // due to the limitations of obcdc and the minimal mode. + // Currently, it only indicates that obcdc has mistakenly identified a NULL value. + bool has_unreliable_null = false; + // xmltype and sdo_geometry type don't support compare operation. bool has_unsupport_type_compare = false; if (OB_SUCC(ret)) { switch(record_type_) { - // Insert records with lob type is accurate. obcdc will output all value of lob type. + // Insert records with null value is accurate. obcdc will output all value accurately. case EINSERT: { if (OB_FAIL(build_insert_stmt_(redo_stmt_, new_cols, new_col_cnt, tbl_meta))) { LOG_ERROR("build insert redo stmt failed", KPC(this)); } else { if (OB_FAIL(build_delete_stmt_(undo_stmt_, new_cols, new_col_cnt, - tbl_meta, has_lob_null, has_unsupport_type_compare))) { + tbl_meta, has_unreliable_null, has_unsupport_type_compare))) { LOG_ERROR("build insert undo stmt failed", KPC(this)); } else { - // ignore has_lob_null + // ignore has_unreliable_null if (has_unsupport_type_compare) { APPEND_STMT(undo_stmt_, "/* POTENTIALLY INACCURATE */"); } @@ -467,25 +468,25 @@ int ObLogMinerRecord::build_dml_stmt_(ICDCRecord &cdc_rec) break; } - // Update records with lob type maybe inaccurate, + // Update records with null value maybe inaccurate, // if NULL value appears in the pre/post mirror, the NULL may be incorrect. case EUPDATE: { if (OB_FAIL(build_update_stmt_(redo_stmt_, new_cols, new_col_cnt, old_cols, - old_col_cnt, tbl_meta, has_lob_null, has_unsupport_type_compare))) { + old_col_cnt, tbl_meta, has_unreliable_null, has_unsupport_type_compare))) { LOG_ERROR("build update redo stmt failed", KPC(this)); } else { - if (has_lob_null || has_unsupport_type_compare) { + if (has_unreliable_null || has_unsupport_type_compare) { APPEND_STMT(redo_stmt_, "/* POTENTIALLY INACCURATE */"); - has_lob_null = false; + has_unreliable_null = false; has_unsupport_type_compare = false; } } if (OB_SUCC(ret)) { if (OB_FAIL(build_update_stmt_(undo_stmt_, old_cols, old_col_cnt, new_cols, - new_col_cnt, tbl_meta, has_lob_null, has_unsupport_type_compare))) { + new_col_cnt, tbl_meta, has_unreliable_null, has_unsupport_type_compare))) { LOG_ERROR("build update undo stmt failed", KPC(this)); } else { - if (has_lob_null || has_unsupport_type_compare) { + if (has_unreliable_null || has_unsupport_type_compare) { APPEND_STMT(undo_stmt_, "/* POTENTIALLY INACCURATE */"); } } @@ -493,25 +494,25 @@ int ObLogMinerRecord::build_dml_stmt_(ICDCRecord &cdc_rec) break; } - // Delete records with lob type maybe inaccurate, + // Delete records with null value maybe inaccurate, // if NULL value appears in the pre mirror, the NULL may be incorrect. case EDELETE: { if (OB_FAIL(build_delete_stmt_(redo_stmt_, old_cols, old_col_cnt, - tbl_meta, has_lob_null, has_unsupport_type_compare))) { + tbl_meta, has_unreliable_null, has_unsupport_type_compare))) { LOG_ERROR("build delete redo stmt failed", KPC(this)); } else { - if (has_lob_null || has_unsupport_type_compare) { + if (has_unreliable_null || has_unsupport_type_compare) { APPEND_STMT(redo_stmt_, "/* POTENTIALLY INACCURATE */"); - has_lob_null = false; + has_unreliable_null = false; has_unsupport_type_compare = false; } } if (OB_SUCC(ret)) { if (OB_FAIL(build_insert_stmt_(undo_stmt_, old_cols, - old_col_cnt, tbl_meta, has_lob_null))) { + old_col_cnt, tbl_meta, has_unreliable_null))) { LOG_ERROR("build delete undo stmt failed", KPC(this)); } else { - if (has_lob_null) { + if (has_unreliable_null) { APPEND_STMT(undo_stmt_, "/* POTENTIALLY INACCURATE */"); } } @@ -536,9 +537,9 @@ int ObLogMinerRecord::build_insert_stmt_(ObStringBuffer &stmt, ITableMeta *tbl_meta) { int ret = OB_SUCCESS; - // ignore has_lob_null - bool has_lob_null = false; - if (OB_FAIL(build_insert_stmt_(stmt, new_cols, new_col_cnt, tbl_meta, has_lob_null))) { + // ignore has_unreliable_null + bool has_unreliable_null = false; + if (OB_FAIL(build_insert_stmt_(stmt, new_cols, new_col_cnt, tbl_meta, has_unreliable_null))) { LOG_ERROR("build insert stmt failed", KPC(this)); } return ret; @@ -547,7 +548,7 @@ int ObLogMinerRecord::build_insert_stmt_(ObStringBuffer &stmt, binlogBuf *new_cols, const unsigned int new_col_cnt, ITableMeta *tbl_meta, - bool &has_lob_null) + bool &has_unreliable_null) { int ret = OB_SUCCESS; if (IS_NOT_INIT) { @@ -594,8 +595,8 @@ int ObLogMinerRecord::build_insert_stmt_(ObStringBuffer &stmt, "col_idx", i); } if (OB_SUCC(ret)) { - if (is_lob_type_(col_meta) && nullptr == new_cols[i].buf) { - has_lob_null = true; + if (nullptr == new_cols[i].buf && new_cols[i].m_origin == VALUE_ORIGIN::PADDING) { + has_unreliable_null = true; } } } @@ -615,8 +616,8 @@ int ObLogMinerRecord::build_update_stmt_(ObStringBuffer &stmt, binlogBuf *old_cols, const unsigned int old_col_cnt, ITableMeta *tbl_meta, - bool &has_lob_null, - bool &has_unsupport_type_compare) + bool &has_unreliable_null, + bool &has_unsupport_type_compare) { int ret = OB_SUCCESS; if (IS_NOT_INIT) { @@ -653,15 +654,16 @@ int ObLogMinerRecord::build_update_stmt_(ObStringBuffer &stmt, "col_idx", i); } if (OB_SUCC(ret)) { - if (is_lob_type_(col_meta) && nullptr == new_cols[i].buf) { - has_lob_null = true; + if ((nullptr == new_cols[i].buf && new_cols[i].m_origin == VALUE_ORIGIN::PADDING) + || (nullptr != old_cols[i].buf && old_cols[i].m_origin == VALUE_ORIGIN::PADDING)) { + has_unreliable_null = true; } } } APPEND_STMT(stmt, " WHERE "); if (OB_SUCC(ret) && OB_FAIL(build_where_conds_(stmt, old_cols, old_col_cnt, - tbl_meta, has_lob_null, has_unsupport_type_compare))) { + tbl_meta, has_unreliable_null, has_unsupport_type_compare))) { LOG_ERROR("build where conds failed",); } if (lib::Worker::CompatMode::MYSQL == compat_mode_) { @@ -686,8 +688,8 @@ int ObLogMinerRecord::build_delete_stmt_(ObStringBuffer &stmt, binlogBuf *old_cols, const unsigned int old_col_cnt, ITableMeta *tbl_meta, - bool &has_lob_null, - bool &has_unsupport_type_compare) + bool &has_unreliable_null, + bool &has_unsupport_type_compare) { int ret = OB_SUCCESS; if (IS_NOT_INIT) { @@ -705,7 +707,7 @@ int ObLogMinerRecord::build_delete_stmt_(ObStringBuffer &stmt, APPEND_STMT(stmt, " WHERE "); if (OB_SUCC(ret) && OB_FAIL(build_where_conds_(stmt, old_cols, old_col_cnt, - tbl_meta, has_lob_null, has_unsupport_type_compare))) { + tbl_meta, has_unreliable_null, has_unsupport_type_compare))) { LOG_ERROR("build where conds failed",); } if (lib::Worker::CompatMode::MYSQL == compat_mode_) { @@ -861,21 +863,21 @@ int ObLogMinerRecord::build_column_value_(ObStringBuffer &stmt, } int ObLogMinerRecord::build_where_conds_(ObStringBuffer &stmt, - binlogBuf *cols, - const unsigned int col_cnt, - ITableMeta *tbl_meta, - bool &has_lob_null, - bool &has_unsupport_type_compare) + binlogBuf *cols, + const unsigned int col_cnt, + ITableMeta *tbl_meta, + bool &has_unreliable_null, + bool &has_unsupport_type_compare) { int ret = OB_SUCCESS; if (!unique_keys_.empty()) { if (OB_FAIL(build_key_conds_(stmt, cols, col_cnt, tbl_meta, - unique_keys_, has_lob_null, has_unsupport_type_compare))) { + unique_keys_, has_unreliable_null, has_unsupport_type_compare))) { LOG_ERROR("build unique keys failed", K(stmt), K(unique_keys_)); } } else if (!primary_keys_.empty()) { if (OB_FAIL(build_key_conds_(stmt, cols, col_cnt, tbl_meta, - primary_keys_, has_lob_null, has_unsupport_type_compare))) { + primary_keys_, has_unreliable_null, has_unsupport_type_compare))) { LOG_ERROR("build primary keys failed", K(stmt), K(primary_keys_)); } } else { @@ -885,7 +887,7 @@ int ObLogMinerRecord::build_where_conds_(ObStringBuffer &stmt, APPEND_STMT(stmt, " AND "); } if (OB_SUCC(ret)) { - if (OB_FAIL(build_cond_(stmt, cols, i, tbl_meta, col_meta, has_lob_null, has_unsupport_type_compare))) { + if (OB_FAIL(build_cond_(stmt, cols, i, tbl_meta, col_meta, has_unreliable_null, has_unsupport_type_compare))) { LOG_ERROR("build cond failed", "table_name", tbl_meta->getName()); } } @@ -895,12 +897,12 @@ int ObLogMinerRecord::build_where_conds_(ObStringBuffer &stmt, } int ObLogMinerRecord::build_key_conds_(ObStringBuffer &stmt, - binlogBuf *cols, - const unsigned int col_cnt, - ITableMeta *tbl_meta, - const KeyArray &key, - bool &has_lob_null, - bool &has_unsupport_type_compare) + binlogBuf *cols, + const unsigned int col_cnt, + ITableMeta *tbl_meta, + const KeyArray &key, + bool &has_unreliable_null, + bool &has_unsupport_type_compare) { int ret = OB_SUCCESS; for (int i = 0; OB_SUCC(ret) && i < key.count(); i++) { @@ -915,7 +917,7 @@ int ObLogMinerRecord::build_key_conds_(ObStringBuffer &stmt, } if (OB_SUCC(ret)) { if (OB_FAIL(build_cond_(stmt, cols, col_idx, tbl_meta, col_meta, - has_lob_null, has_unsupport_type_compare))) { + has_unreliable_null, has_unsupport_type_compare))) { LOG_ERROR("build cond failed", "table_name", tbl_meta->getName()); } } @@ -925,12 +927,12 @@ int ObLogMinerRecord::build_key_conds_(ObStringBuffer &stmt, } int ObLogMinerRecord::build_cond_(ObStringBuffer &stmt, - binlogBuf *cols, - const unsigned int col_idx, - ITableMeta *tbl_meta, - IColMeta *col_meta, - bool &has_lob_null, - bool &has_unsupport_type_compare) + binlogBuf *cols, + const unsigned int col_idx, + ITableMeta *tbl_meta, + IColMeta *col_meta, + bool &has_unreliable_null, + bool &has_unsupport_type_compare) { int ret = OB_SUCCESS; if (OB_ISNULL(col_meta)) { @@ -940,7 +942,7 @@ int ObLogMinerRecord::build_cond_(ObStringBuffer &stmt, if (is_lob_type_(col_meta) && nullptr != cols[col_idx].buf) { // build lob type compare condition, excluding null value condition if (OB_FAIL(build_lob_cond_(stmt, cols, col_idx, tbl_meta, - col_meta, has_lob_null, has_unsupport_type_compare))) { + col_meta, has_unreliable_null, has_unsupport_type_compare))) { LOG_ERROR("build lob condition failed", "table_name", tbl_meta->getName()); } } else { @@ -949,8 +951,8 @@ int ObLogMinerRecord::build_cond_(ObStringBuffer &stmt, } } if (OB_SUCC(ret)) { - if (is_lob_type_(col_meta) && nullptr == cols[col_idx].buf) { - has_lob_null = true; + if (nullptr == cols[col_idx].buf && cols[col_idx].m_origin == VALUE_ORIGIN::PADDING) { + has_unreliable_null = true; } } } @@ -958,12 +960,12 @@ int ObLogMinerRecord::build_cond_(ObStringBuffer &stmt, } int ObLogMinerRecord::build_lob_cond_(ObStringBuffer &stmt, - binlogBuf *cols, - const unsigned int col_idx, - ITableMeta *tbl_meta, - IColMeta *col_meta, - bool &has_lob_null, - bool &has_unsupport_type_compare) + binlogBuf *cols, + const unsigned int col_idx, + ITableMeta *tbl_meta, + IColMeta *col_meta, + bool &has_unreliable_null, + bool &has_unsupport_type_compare) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!is_lob_type_(col_meta) || nullptr == cols[col_idx].buf)) { @@ -1020,10 +1022,10 @@ int ObLogMinerRecord::build_lob_cond_(ObStringBuffer &stmt, } int ObLogMinerRecord::build_func_cond_(ObStringBuffer &stmt, - binlogBuf *cols, - const unsigned int col_idx, + binlogBuf *cols, + const unsigned int col_idx, ITableMeta *tbl_meta, - IColMeta *col_meta, + IColMeta *col_meta, const char *func_name) { int ret = OB_SUCCESS; @@ -1042,10 +1044,10 @@ int ObLogMinerRecord::build_func_cond_(ObStringBuffer &stmt, } int ObLogMinerRecord::build_normal_cond_(ObStringBuffer &stmt, - binlogBuf *cols, - const unsigned int col_idx, - ITableMeta *tbl_meta, - IColMeta *col_meta) + binlogBuf *cols, + const unsigned int col_idx, + ITableMeta *tbl_meta, + IColMeta *col_meta) { int ret = OB_SUCCESS; APPEND_ESCAPE_CHAR(stmt); diff --git a/src/share/ob_lob_access_utils.cpp b/src/share/ob_lob_access_utils.cpp index 050a42f0f..daadf19b3 100644 --- a/src/share/ob_lob_access_utils.cpp +++ b/src/share/ob_lob_access_utils.cpp @@ -1154,7 +1154,7 @@ int ObTextStringResult::fill_inrow_templob_header(const int64_t inrow_data_len, if (OB_ISNULL(buf) || (buf_len == 0)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("Lob: try to fill inrow templob header with empty buffer", - K(ret), K(inrow_data_len), K(buf), K(buf_len)); + K(ret), K(inrow_data_len), KP(buf), K(buf_len)); } else if (inrow_data_len <= OB_MAX_LONGTEXT_LENGTH - MAX_TMP_LOB_HEADER_LEN) { ObLobLocatorV2 locator(buf, static_cast(buf_len), true); // temp lob in oracle mode not need extern neither, for it does not have rowkey @@ -1171,13 +1171,13 @@ int ObTextStringResult::fill_inrow_templob_header(const int64_t inrow_data_len, 0, 0, false))) { - LOG_WARN("Lob: fill temp lob locator failed", K(ret), K(inrow_data_len), K(buf), K(buf_len)); + LOG_WARN("Lob: fill temp lob locator failed", K(ret), K(inrow_data_len), KP(buf), K(buf_len)); } else if (OB_FAIL((locator.set_payload_data(&lob_common, empty_str)))) { - LOG_WARN("Lob: set temp lob locator payload failed", K(ret), K(inrow_data_len), K(buf), K(buf_len)); + LOG_WARN("Lob: set temp lob locator payload failed", K(ret), K(inrow_data_len), KP(buf), K(buf_len)); } } else { // oversized ret = OB_NOT_SUPPORTED; - LOG_WARN("Lob: not support length bigger than 512M", K(ret), K(inrow_data_len), K(buf), K(buf_len)); + LOG_WARN("Lob: not support length bigger than 512M", K(ret), K(inrow_data_len), KP(buf), K(buf_len)); } return ret; } diff --git a/src/share/vector_index/ob_plugin_vector_index_serialize.cpp b/src/share/vector_index/ob_plugin_vector_index_serialize.cpp index 915f503ad..f526489cb 100644 --- a/src/share/vector_index/ob_plugin_vector_index_serialize.cpp +++ b/src/share/vector_index/ob_plugin_vector_index_serialize.cpp @@ -250,7 +250,7 @@ int ObHNSWDeserializeCallback::operator()(char*& data, const int64_t data_size, ObDatum data_datum; ObHNSWDeserializeCallback::CbParam ¶m = static_cast(cb_param); ObTableScanIterator *row_iter = static_cast(param.iter_); - ObIAllocator *alloactor = param.allocator_; + ObIAllocator *allocator = param.allocator_; ObTextStringIter *&str_iter = param.str_iter_; ObTextStringIterState state; ObString src_block_data; @@ -272,18 +272,18 @@ int ObHNSWDeserializeCallback::operator()(char*& data, const int64_t data_size, // current lob is end, need to switch to next lob // release current str iter str_iter->~ObTextStringIter(); - alloactor->free(str_iter); + allocator->free(str_iter); str_iter = nullptr; - alloactor->reuse(); + allocator->reuse(); } else { ret = (str_iter->get_inner_ret() != OB_SUCCESS) ? str_iter->get_inner_ret() : OB_INVALID_DATA; LOG_WARN("iter state invalid", K(ret), K(state), KPC(str_iter)); // return error, release current str iter str_iter->~ObTextStringIter(); - alloactor->free(str_iter); + allocator->free(str_iter); str_iter = nullptr; - alloactor->reuse(); + allocator->reuse(); } } if (OB_SUCC(ret) && OB_ISNULL(str_iter)) { @@ -297,10 +297,10 @@ int ObHNSWDeserializeCallback::operator()(char*& data, const int64_t data_size, key_datum = row->storage_datums_[0]; data_datum = row->storage_datums_[1]; LOG_INFO("[vec index debug] show key and data for vsag deserialize", K(key_datum), K(data_datum)); - if (OB_ISNULL(str_iter = OB_NEWx(ObTextStringIter, alloactor, ObLongTextType, CS_TYPE_BINARY, data_datum.get_string(), true))) { + if (OB_ISNULL(str_iter = OB_NEWx(ObTextStringIter, allocator, ObLongTextType, CS_TYPE_BINARY, data_datum.get_string(), true))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("fail to new ObTextStringIter", KR(ret)); - } else if (OB_FAIL(str_iter->init(0, NULL, alloactor))) { + } else if (OB_FAIL(str_iter->init(0, NULL, allocator))) { LOG_WARN("init lob str iter failed ", K(ret)); } } diff --git a/src/share/vector_index/ob_plugin_vector_index_service.cpp b/src/share/vector_index/ob_plugin_vector_index_service.cpp index 776b699cc..496e21cf2 100644 --- a/src/share/vector_index/ob_plugin_vector_index_service.cpp +++ b/src/share/vector_index/ob_plugin_vector_index_service.cpp @@ -29,7 +29,7 @@ ObPluginVectorIndexMgr::~ObPluginVectorIndexMgr() void ObPluginVectorIndexMgr::destroy() { if (IS_INIT) { - LOG_INFO("LS Vector Index Mgr destory", K(ls_id_)); + LOG_INFO("LS Vector Index Mgr destroy", K(ls_id_)); is_inited_ = false; need_check_ = false; ls_id_.reset(); diff --git a/src/sql/engine/expr/ob_datum_cast.cpp b/src/sql/engine/expr/ob_datum_cast.cpp index aa976ba6c..4b7e9ee8f 100644 --- a/src/sql/engine/expr/ob_datum_cast.cpp +++ b/src/sql/engine/expr/ob_datum_cast.cpp @@ -2892,7 +2892,7 @@ int common_datetime_string(const ObExpr &expr, const ObObjType in_type, const Ob if (OB_SUCC(ret) && OB_FAIL(ObTimeConverter::datetime_to_str(in_val, tz_info, nls_format, in_scale, buf, buf_len, out_len))) { LOG_WARN("failed to convert datetime to string", K(ret), K(in_val), KP(tz_info), - K(nls_format), K(in_scale), K(buf), K(out_len)); + K(nls_format), K(in_scale), KP(buf), K(out_len)); } } } @@ -6700,7 +6700,7 @@ CAST_FUNC_NAME(bit, datetime) char buf[BUF_LEN] = {0}; ObLengthSemantics length = expr.args_[0]->datum_meta_.length_semantics_; if (OB_FAIL(bit_to_char_array(in_val, length, buf, BUF_LEN, pos))) { - LOG_WARN("fail to store val", K(buf), K(BUF_LEN), K(in_val), K(pos)); + LOG_WARN("fail to store val", KP(buf), K(BUF_LEN), K(in_val), K(pos)); } else { ObObjType out_type = expr.datum_meta_.type_; ObString str(pos, buf); @@ -6749,7 +6749,7 @@ CAST_FUNC_NAME(bit, date) char buf[BUF_LEN] = {0}; ObLengthSemantics length = expr.args_[0]->datum_meta_.length_semantics_; if (OB_FAIL(bit_to_char_array(in_val, length, buf, BUF_LEN, pos))) { - LOG_WARN("fail to store val", K(buf), K(BUF_LEN), K(in_val), K(pos)); + LOG_WARN("fail to store val", KP(buf), K(BUF_LEN), K(in_val), K(pos)); } else { ObString str(pos, buf); if (CAST_FAIL(ObTimeConverter::str_to_date(str, out_val, date_sql_mode))) { @@ -6784,7 +6784,7 @@ CAST_FUNC_NAME(bit, time) char buf[BUF_LEN] = {0}; ObLengthSemantics length = expr.args_[0]->datum_meta_.length_semantics_; if (OB_FAIL(bit_to_char_array(in_val, length, buf, BUF_LEN, pos))) { - LOG_WARN("fail to store val", K(buf), K(BUF_LEN), K(in_val), K(pos)); + LOG_WARN("fail to store val", KP(buf), K(BUF_LEN), K(in_val), K(pos)); } else { ObString str(pos, buf); ObScale res_scale; @@ -6834,7 +6834,7 @@ CAST_FUNC_NAME(bit, string) char buf[BUF_LEN] = {0}; ObLengthSemantics length = expr.args_[0]->datum_meta_.length_semantics_; if (OB_FAIL(bit_to_char_array(in_val, length, buf, BUF_LEN, pos))) { - LOG_WARN("fail to store val", K(ret), K(in_val), K(length), K(buf), K(BUF_LEN), K(pos)); + LOG_WARN("fail to store val", K(ret), K(in_val), K(length), KP(buf), K(BUF_LEN), K(pos)); } else { ObString str(pos, buf); bool has_set_res = false; @@ -6866,7 +6866,7 @@ CAST_FUNC_NAME(bit, text) char buf[BUF_LEN] = {0}; ObLengthSemantics length = expr.args_[0]->datum_meta_.length_semantics_; if (OB_FAIL(bit_to_char_array(in_val, length, buf, BUF_LEN, pos))) { - LOG_WARN("fail to store val", K(ret), K(in_val), K(length), K(buf), K(BUF_LEN), K(pos)); + LOG_WARN("fail to store val", K(ret), K(in_val), K(length), KP(buf), K(BUF_LEN), K(pos)); } else { ObString str(pos, buf); ObString res_str; @@ -6894,7 +6894,7 @@ CAST_FUNC_NAME(bit, json) uint64_t in_val = child_res->get_uint(); ObLengthSemantics length = expr.args_[0]->datum_meta_.length_semantics_; if (OB_FAIL(bit_to_char_array(in_val, length, buf, BUF_LEN, pos))) { - LOG_WARN("fail to store val", K(ret), K(in_val), K(length), K(buf), K(BUF_LEN), K(pos)); + LOG_WARN("fail to store val", K(ret), K(in_val), K(length), KP(buf), K(BUF_LEN), K(pos)); } else { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); @@ -6904,7 +6904,7 @@ CAST_FUNC_NAME(bit, json) ObString raw_bin; if (OB_FAIL(ObJsonWrapper::get_raw_binary(j_base, raw_bin, &temp_allocator))) { - LOG_WARN("fail to get int json binary", K(ret), K(in_val), K(buf), K(BUF_LEN)); + LOG_WARN("fail to get int json binary", K(ret), K(in_val), KP(buf), K(BUF_LEN)); } else if (OB_FAIL(common_json_bin(expr, ctx, res_datum, raw_bin))) { LOG_WARN("fail to fill json bin lob locator", K(ret)); } diff --git a/src/storage/tx/ob_tx_log.cpp b/src/storage/tx/ob_tx_log.cpp index fc10ab2d7..f4455bead 100644 --- a/src/storage/tx/ob_tx_log.cpp +++ b/src/storage/tx/ob_tx_log.cpp @@ -656,7 +656,7 @@ int ObTxRedoLog::set_mutator_buf(char *buf) int ret = OB_SUCCESS; if (nullptr == buf || mutator_size_ >= 0) { ret = OB_INVALID_ARGUMENT; - TRANS_LOG(ERROR, "invalid mutator buf", K(buf), K(mutator_size_)); + TRANS_LOG(ERROR, "invalid mutator buf", KP(buf), K(mutator_size_)); } else { mutator_buf_ = buf; } @@ -670,7 +670,7 @@ int ObTxRedoLog::set_mutator_size(const int64_t size, const bool after_fill) || (after_fill && mutator_size_ < size)) { ret = OB_INVALID_ARGUMENT; TRANS_LOG(ERROR, "invalid argument when set mutator size", K(after_fill), K(size), - K(mutator_size_), K(mutator_buf_)); + K(mutator_size_), KP(mutator_buf_)); } else if (!after_fill) { int len = 0; SERIALIZE_SIZE_HEADER(UNIS_VERSION); @@ -1393,7 +1393,7 @@ int ObTxLogBlock::init_for_replay(const char *buf, const int64_t &size) || OB_ISNULL(buf) || size <= 0) { ret = OB_INVALID_ARGUMENT; - TRANS_LOG(ERROR, "invalid argument", K(buf), K(size), K(*this)); + TRANS_LOG(ERROR, "invalid argument", KP(buf), K(size), K(*this)); } else { replay_buf_ = buf; len_ = size; @@ -1415,7 +1415,7 @@ int ObTxLogBlock::init_for_replay(const char *buf, const int64_t &size, int skip ret = OB_INIT_TWICE; } else if (OB_ISNULL(buf) || size <= 0) { ret = OB_INVALID_ARGUMENT; - TRANS_LOG(ERROR, "invalid argument", K(buf), K(size), K(*this)); + TRANS_LOG(ERROR, "invalid argument", KP(buf), K(size), K(*this)); } else { replay_buf_ = buf; len_ = size; diff --git a/unittest/logminer/test_ob_log_miner_record.cpp b/unittest/logminer/test_ob_log_miner_record.cpp index e7b0c24b9..d9b15a0ea 100644 --- a/unittest/logminer/test_ob_log_miner_record.cpp +++ b/unittest/logminer/test_ob_log_miner_record.cpp @@ -65,6 +65,35 @@ TEST(test_ob_log_miner_record, InitObLogMinerRecord) destroy_miner_br(br); record.destroy(); + br = build_logminer_br(new_buf, old_buf, EUPDATE, lib::Worker::CompatMode::MYSQL, + "tenant2.db2", "tbl2", 8, "id", "1", "2", + static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_VAR_STRING), + "name", nullptr, nullptr, static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_VAR_STRING)); + EXPECT_EQ(OB_SUCCESS, record.init(*br)); + EXPECT_STREQ("tenant2", record.tenant_name_.ptr()); + EXPECT_STREQ("db2", record.database_name_.ptr()); + EXPECT_STREQ("tbl2", record.table_name_.ptr()); + EXPECT_EQ(OB_SUCCESS, record.build_stmts(*br)); + EXPECT_STREQ("UPDATE `db2`.`tbl2` SET `id`='1', `name`=NULL WHERE `id`='2' AND `name` IS NULL LIMIT 1;", record.redo_stmt_.ptr()); + EXPECT_STREQ("UPDATE `db2`.`tbl2` SET `id`='2', `name`=NULL WHERE `id`='1' AND `name` IS NULL LIMIT 1;", record.undo_stmt_.ptr()); + destroy_miner_br(br); + record.destroy(); + + br = build_logminer_br(new_buf, old_buf, EUPDATE, lib::Worker::CompatMode::MYSQL, + "tenant2.db2", "tbl2", 8, "id", "1", "2", + static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_VAR_STRING), + "name", nullptr, nullptr, static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_VAR_STRING)); + old_buf[1].m_origin = VALUE_ORIGIN::PADDING; + EXPECT_EQ(OB_SUCCESS, record.init(*br)); + EXPECT_STREQ("tenant2", record.tenant_name_.ptr()); + EXPECT_STREQ("db2", record.database_name_.ptr()); + EXPECT_STREQ("tbl2", record.table_name_.ptr()); + EXPECT_EQ(OB_SUCCESS, record.build_stmts(*br)); + EXPECT_STREQ("UPDATE `db2`.`tbl2` SET `id`='1', `name`=NULL WHERE `id`='2' AND `name` IS NULL LIMIT 1;/* POTENTIALLY INACCURATE */", record.redo_stmt_.ptr()); + EXPECT_STREQ("UPDATE `db2`.`tbl2` SET `id`='2', `name`=NULL WHERE `id`='1' AND `name` IS NULL LIMIT 1;/* POTENTIALLY INACCURATE */", record.undo_stmt_.ptr()); + destroy_miner_br(br); + record.destroy(); + br = build_logminer_br(new_buf, old_buf, EDELETE, lib::Worker::CompatMode::MYSQL, "tenant2.db2", "tbl2", 8, "id", nullptr , "2", static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_VAR_STRING), @@ -79,6 +108,35 @@ TEST(test_ob_log_miner_record, InitObLogMinerRecord) destroy_miner_br(br); record.destroy(); + br = build_logminer_br(new_buf, old_buf, EDELETE, lib::Worker::CompatMode::MYSQL, + "tenant2.db2", "tbl2", 8, "id", nullptr , "2", + static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_VAR_STRING), + "name", nullptr, nullptr, static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_VAR_STRING)); + EXPECT_EQ(OB_SUCCESS, record.init(*br)); + EXPECT_STREQ("tenant2", record.tenant_name_.ptr()); + EXPECT_STREQ("db2", record.database_name_.ptr()); + EXPECT_STREQ("tbl2", record.table_name_.ptr()); + EXPECT_EQ(OB_SUCCESS, record.build_stmts(*br)); + EXPECT_STREQ("DELETE FROM `db2`.`tbl2` WHERE `id`='2' AND `name` IS NULL LIMIT 1;", record.redo_stmt_.ptr()); + EXPECT_STREQ("INSERT INTO `db2`.`tbl2` (`id`, `name`) VALUES ('2', NULL);", record.undo_stmt_.ptr()); + destroy_miner_br(br); + record.destroy(); + + br = build_logminer_br(new_buf, old_buf, EDELETE, lib::Worker::CompatMode::MYSQL, + "tenant2.db2", "tbl2", 8, "id", nullptr , "2", + static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_VAR_STRING), + "name", nullptr, nullptr, static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_VAR_STRING)); + old_buf[1].m_origin = VALUE_ORIGIN::PADDING; + EXPECT_EQ(OB_SUCCESS, record.init(*br)); + EXPECT_STREQ("tenant2", record.tenant_name_.ptr()); + EXPECT_STREQ("db2", record.database_name_.ptr()); + EXPECT_STREQ("tbl2", record.table_name_.ptr()); + EXPECT_EQ(OB_SUCCESS, record.build_stmts(*br)); + EXPECT_STREQ("DELETE FROM `db2`.`tbl2` WHERE `id`='2' AND `name` IS NULL LIMIT 1;/* POTENTIALLY INACCURATE */", record.redo_stmt_.ptr()); + EXPECT_STREQ("INSERT INTO `db2`.`tbl2` (`id`, `name`) VALUES ('2', NULL);/* POTENTIALLY INACCURATE */", record.undo_stmt_.ptr()); + destroy_miner_br(br); + record.destroy(); + br = build_logminer_br(new_buf, old_buf, EDDL, lib::Worker::CompatMode::MYSQL, "tenant2.db2", "", 4, "ddl_stmt_str", "CREATE TABLE T1(ID INT PRIMARY KEY);" , nullptr, static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_VAR_STRING)); @@ -442,6 +500,8 @@ TEST(test_ob_log_miner_record, LobTypeInMySqlMode) "tenant2.db2", "tbl2", "utf8mb4", 8, "col1", "{\"key\": \"new\"}", nullptr, static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_JSON), "col2", "POINT(0 1)", "POINT(2 3)", static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_GEOMETRY)); + new_buf[0].m_origin = VALUE_ORIGIN::PADDING; + old_buf[0].m_origin = VALUE_ORIGIN::PADDING; EXPECT_EQ(OB_SUCCESS, record.init(*br)); EXPECT_STREQ("tenant2", record.tenant_name_.ptr()); EXPECT_STREQ("db2", record.database_name_.ptr()); @@ -459,6 +519,8 @@ TEST(test_ob_log_miner_record, LobTypeInMySqlMode) "col2", "POINT(0 1)", "POINT(2 3)", static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_GEOMETRY), "col3", "1", nullptr, static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_LONG)); br->get_br()->getTableMeta()->setUKs("col3"); + new_buf[0].m_origin = VALUE_ORIGIN::PADDING; + old_buf[0].m_origin = VALUE_ORIGIN::PADDING; EXPECT_EQ(OB_SUCCESS, record.init(*br)); EXPECT_STREQ("tenant2", record.tenant_name_.ptr()); EXPECT_STREQ("db2", record.database_name_.ptr()); @@ -469,6 +531,110 @@ TEST(test_ob_log_miner_record, LobTypeInMySqlMode) destroy_miner_br(br); record.destroy(); + // delete without key + br = build_logminer_br(new_buf, old_buf, EDELETE, lib::Worker::CompatMode::MYSQL, + "tenant2.db2", "tbl2", "utf8mb4", 8, + "col1", nullptr, "{\"key\": \"old\"}", static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_JSON), + "col2", nullptr, "POINT(2 3)", static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_GEOMETRY)); + new_buf[0].m_origin = VALUE_ORIGIN::PADDING; + old_buf[0].m_origin = VALUE_ORIGIN::PADDING; + EXPECT_EQ(OB_SUCCESS, record.init(*br)); + EXPECT_STREQ("tenant2", record.tenant_name_.ptr()); + EXPECT_STREQ("db2", record.database_name_.ptr()); + EXPECT_STREQ("tbl2", record.table_name_.ptr()); + EXPECT_EQ(OB_SUCCESS, record.build_stmts(*br)); + EXPECT_STREQ("DELETE FROM `db2`.`tbl2` WHERE `col1`=cast('{\"key\": \"old\"}'as json) AND ST_Equals(`col2`, ST_GeomFromText('POINT(2 3)')) LIMIT 1;", record.redo_stmt_.ptr()); + EXPECT_STREQ("INSERT INTO `db2`.`tbl2` (`col1`, `col2`) VALUES ('{\"key\": \"old\"}', ST_GeomFromText('POINT(2 3)'));", record.undo_stmt_.ptr()); + destroy_miner_br(br); + record.destroy(); + + // delete with key + br = build_logminer_br(new_buf, old_buf, EDELETE, lib::Worker::CompatMode::MYSQL, + "tenant2.db2", "tbl2", "utf8mb4", 12, + "col1", nullptr, "{\"key\": \"old\"}", static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_JSON), + "col2", nullptr, "POINT(2 3)", static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_GEOMETRY), + "col3", nullptr, "2", static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_LONG)); + br->get_br()->getTableMeta()->setUKs("col3"); + new_buf[1].m_origin = VALUE_ORIGIN::PADDING; + old_buf[1].m_origin = VALUE_ORIGIN::PADDING; + EXPECT_EQ(OB_SUCCESS, record.init(*br)); + EXPECT_STREQ("tenant2", record.tenant_name_.ptr()); + EXPECT_STREQ("db2", record.database_name_.ptr()); + EXPECT_STREQ("tbl2", record.table_name_.ptr()); + EXPECT_EQ(OB_SUCCESS, record.build_stmts(*br)); + EXPECT_STREQ("DELETE FROM `db2`.`tbl2` WHERE `col3`=2 LIMIT 1;", record.redo_stmt_.ptr()); + EXPECT_STREQ("INSERT INTO `db2`.`tbl2` (`col1`, `col2`, `col3`) VALUES ('{\"key\": \"old\"}', ST_GeomFromText('POINT(2 3)'), 2);", record.undo_stmt_.ptr()); + destroy_miner_br(br); + record.destroy(); + + // null value delete without key + br = build_logminer_br(new_buf, old_buf, EDELETE, lib::Worker::CompatMode::MYSQL, + "tenant2.db2", "tbl2", "utf8mb4", 8, + "col1", nullptr, nullptr, static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_JSON), + "col2", nullptr, "POINT(2 3)", static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_GEOMETRY)); + new_buf[0].m_origin = VALUE_ORIGIN::PADDING; + old_buf[0].m_origin = VALUE_ORIGIN::PADDING; + EXPECT_EQ(OB_SUCCESS, record.init(*br)); + EXPECT_STREQ("tenant2", record.tenant_name_.ptr()); + EXPECT_STREQ("db2", record.database_name_.ptr()); + EXPECT_STREQ("tbl2", record.table_name_.ptr()); + EXPECT_EQ(OB_SUCCESS, record.build_stmts(*br)); + EXPECT_STREQ("DELETE FROM `db2`.`tbl2` WHERE `col1` IS NULL AND ST_Equals(`col2`, ST_GeomFromText('POINT(2 3)')) LIMIT 1;/* POTENTIALLY INACCURATE */",record.redo_stmt_.ptr()); + EXPECT_STREQ("INSERT INTO `db2`.`tbl2` (`col1`, `col2`) VALUES (NULL, ST_GeomFromText('POINT(2 3)'));/* POTENTIALLY INACCURATE */", record.undo_stmt_.ptr()); + destroy_miner_br(br); + record.destroy(); + + // null value delete with key + br = build_logminer_br(new_buf, old_buf, EDELETE, lib::Worker::CompatMode::MYSQL, + "tenant2.db2", "tbl2", "utf8mb4", 12, + "col1", nullptr, nullptr, static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_JSON), + "col2", nullptr, "POINT(2 3)", static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_GEOMETRY), + "col3", nullptr, "1", static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_LONG)); + new_buf[0].m_origin = VALUE_ORIGIN::PADDING; + old_buf[0].m_origin = VALUE_ORIGIN::PADDING; + br->get_br()->getTableMeta()->setUKs("col3"); + EXPECT_EQ(OB_SUCCESS, record.init(*br)); + EXPECT_STREQ("tenant2", record.tenant_name_.ptr()); + EXPECT_STREQ("db2", record.database_name_.ptr()); + EXPECT_STREQ("tbl2", record.table_name_.ptr()); + EXPECT_EQ(OB_SUCCESS, record.build_stmts(*br)); + EXPECT_STREQ("DELETE FROM `db2`.`tbl2` WHERE `col3`=1 LIMIT 1;", record.redo_stmt_.ptr()); + EXPECT_STREQ("INSERT INTO `db2`.`tbl2` (`col1`, `col2`, `col3`) VALUES (NULL, ST_GeomFromText('POINT(2 3)'), 1);/* POTENTIALLY INACCURATE */", record.undo_stmt_.ptr()); + destroy_miner_br(br); + record.destroy(); + + // null value update without key + br = build_logminer_br(new_buf, old_buf, EUPDATE, lib::Worker::CompatMode::MYSQL, + "tenant2.db2", "tbl2", "utf8mb4", 8, + "col1", "{\"key\": \"new\"}", nullptr, static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_JSON), + "col2", "POINT(0 1)", "POINT(2 3)", static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_GEOMETRY)); + EXPECT_EQ(OB_SUCCESS, record.init(*br)); + EXPECT_STREQ("tenant2", record.tenant_name_.ptr()); + EXPECT_STREQ("db2", record.database_name_.ptr()); + EXPECT_STREQ("tbl2", record.table_name_.ptr()); + EXPECT_EQ(OB_SUCCESS, record.build_stmts(*br)); + EXPECT_STREQ("UPDATE `db2`.`tbl2` SET `col1`='{\"key\": \"new\"}', `col2`=ST_GeomFromText('POINT(0 1)') WHERE `col1` IS NULL AND ST_Equals(`col2`, ST_GeomFromText('POINT(2 3)')) LIMIT 1;",record.redo_stmt_.ptr()); + EXPECT_STREQ("UPDATE `db2`.`tbl2` SET `col1`=NULL, `col2`=ST_GeomFromText('POINT(2 3)') WHERE `col1`=cast('{\"key\": \"new\"}'as json) AND ST_Equals(`col2`, ST_GeomFromText('POINT(0 1)')) LIMIT 1;", record.undo_stmt_.ptr()); + destroy_miner_br(br); + record.destroy(); + + // null value update with key + br = build_logminer_br(new_buf, old_buf, EUPDATE, lib::Worker::CompatMode::MYSQL, + "tenant2.db2", "tbl2", "utf8mb4", 12, + "col1", "{\"key\": \"new\"}", nullptr, static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_JSON), + "col2", "POINT(0 1)", "POINT(2 3)", static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_GEOMETRY), + "col3", "1", nullptr, static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_LONG)); + br->get_br()->getTableMeta()->setUKs("col3"); + EXPECT_EQ(OB_SUCCESS, record.init(*br)); + EXPECT_STREQ("tenant2", record.tenant_name_.ptr()); + EXPECT_STREQ("db2", record.database_name_.ptr()); + EXPECT_STREQ("tbl2", record.table_name_.ptr()); + EXPECT_EQ(OB_SUCCESS, record.build_stmts(*br)); + EXPECT_STREQ("UPDATE `db2`.`tbl2` SET `col1`='{\"key\": \"new\"}', `col2`=ST_GeomFromText('POINT(0 1)'), `col3`=1 WHERE `col3` IS NULL LIMIT 1;", record.redo_stmt_.ptr()); + EXPECT_STREQ("UPDATE `db2`.`tbl2` SET `col1`=NULL, `col2`=ST_GeomFromText('POINT(2 3)'), `col3`=NULL WHERE `col3`=1 LIMIT 1;", record.undo_stmt_.ptr()); + destroy_miner_br(br); + record.destroy(); + // delete without key br = build_logminer_br(new_buf, old_buf, EDELETE, lib::Worker::CompatMode::MYSQL, "tenant2.db2", "tbl2", "utf8mb4", 8, @@ -511,8 +677,8 @@ TEST(test_ob_log_miner_record, LobTypeInMySqlMode) EXPECT_STREQ("db2", record.database_name_.ptr()); EXPECT_STREQ("tbl2", record.table_name_.ptr()); EXPECT_EQ(OB_SUCCESS, record.build_stmts(*br)); - EXPECT_STREQ("DELETE FROM `db2`.`tbl2` WHERE `col1` IS NULL AND ST_Equals(`col2`, ST_GeomFromText('POINT(2 3)')) LIMIT 1;/* POTENTIALLY INACCURATE */",record.redo_stmt_.ptr()); - EXPECT_STREQ("INSERT INTO `db2`.`tbl2` (`col1`, `col2`) VALUES (NULL, ST_GeomFromText('POINT(2 3)'));/* POTENTIALLY INACCURATE */", record.undo_stmt_.ptr()); + EXPECT_STREQ("DELETE FROM `db2`.`tbl2` WHERE `col1` IS NULL AND ST_Equals(`col2`, ST_GeomFromText('POINT(2 3)')) LIMIT 1;",record.redo_stmt_.ptr()); + EXPECT_STREQ("INSERT INTO `db2`.`tbl2` (`col1`, `col2`) VALUES (NULL, ST_GeomFromText('POINT(2 3)'));", record.undo_stmt_.ptr()); destroy_miner_br(br); record.destroy(); @@ -529,7 +695,7 @@ TEST(test_ob_log_miner_record, LobTypeInMySqlMode) EXPECT_STREQ("tbl2", record.table_name_.ptr()); EXPECT_EQ(OB_SUCCESS, record.build_stmts(*br)); EXPECT_STREQ("DELETE FROM `db2`.`tbl2` WHERE `col3`=1 LIMIT 1;", record.redo_stmt_.ptr()); - EXPECT_STREQ("INSERT INTO `db2`.`tbl2` (`col1`, `col2`, `col3`) VALUES (NULL, ST_GeomFromText('POINT(2 3)'), 1);/* POTENTIALLY INACCURATE */", record.undo_stmt_.ptr()); + EXPECT_STREQ("INSERT INTO `db2`.`tbl2` (`col1`, `col2`, `col3`) VALUES (NULL, ST_GeomFromText('POINT(2 3)'), 1);", record.undo_stmt_.ptr()); destroy_miner_br(br); record.destroy(); } @@ -673,6 +839,8 @@ TEST(test_ob_log_miner_record, LobTypeInOracleMode) "col2", "SRID=NULL;POINT(0 1)", nullptr, static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_GEOMETRY), "col3", nullptr, nullptr, drcmsg_field_types::DRCMSG_TYPE_ORA_XML, "col4", "AABB1122", "1122", static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_ORA_CLOB)); + new_buf[1].m_origin = VALUE_ORIGIN::PADDING; + old_buf[1].m_origin = VALUE_ORIGIN::PADDING; EXPECT_EQ(OB_SUCCESS, record.init(*br)); EXPECT_STREQ("tenant2", record.tenant_name_.ptr()); EXPECT_STREQ("db2", record.database_name_.ptr()); @@ -749,6 +917,8 @@ TEST(test_ob_log_miner_record, LobTypeInOracleMode) "col2", nullptr, nullptr, static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_GEOMETRY), "col3", nullptr, "abc", drcmsg_field_types::DRCMSG_TYPE_ORA_XML, "col4", nullptr, "AABB1122", static_cast(obmysql::EMySQLFieldType::MYSQL_TYPE_ORA_CLOB)); + new_buf[1].m_origin = VALUE_ORIGIN::PADDING; + old_buf[1].m_origin = VALUE_ORIGIN::PADDING; EXPECT_EQ(OB_SUCCESS, record.init(*br)); EXPECT_STREQ("tenant2", record.tenant_name_.ptr()); EXPECT_STREQ("db2", record.database_name_.ptr()); @@ -777,6 +947,7 @@ TEST(test_ob_log_miner_record, LobTypeInOracleMode) EXPECT_STREQ("INSERT INTO \"db2\".\"tbl2\" (\"col1\", \"col2\", \"col3\", \"col4\", \"col5\") VALUES ('{\"key\": \"value\"}', SDO_GEOMETRY('POINT(0 1)', NULL), 'abc', 'AABB1122', 1);", record.undo_stmt_.ptr()); destroy_miner_br(br); record.destroy(); + } } @@ -792,4 +963,4 @@ int main(int argc, char **argv) logger.set_enable_async_log(false); testing::InitGoogleTest(&argc,argv); return RUN_ALL_TESTS(); -} +} \ No newline at end of file