From cd0ec2662a1147c5f3d42b257a988f9e66e75f00 Mon Sep 17 00:00:00 2001 From: obdev Date: Thu, 24 Aug 2023 09:10:26 +0000 Subject: [PATCH] fix: fix update ignore bug that will lost data when has cross-partition update --- src/share/object/ob_obj_cast.cpp | 24 ++++++++++++++++--- src/share/object/ob_obj_cast.h | 6 ++++- src/sql/engine/dml/ob_dml_service.cpp | 17 +++++++++---- src/sql/engine/dml/ob_dml_service.h | 2 +- .../static/ob_px_multi_part_insert_op.cpp | 2 +- 5 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/share/object/ob_obj_cast.cpp b/src/share/object/ob_obj_cast.cpp index dd2a893497..229726522a 100644 --- a/src/share/object/ob_obj_cast.cpp +++ b/src/share/object/ob_obj_cast.cpp @@ -32,6 +32,8 @@ #include "sql/engine/expr/ob_expr_lob_utils.h" #include "lib/charset/ob_charset.h" #include "lib/geo/ob_geometry_cast.h" +#include "sql/engine/expr/ob_datum_cast.h" + #ifdef OB_BUILD_ORACLE_XML #include "lib/xml/ob_xml_util.h" #include "lib/xml/ob_xml_parser.h" @@ -13147,14 +13149,30 @@ int ObObjCaster::to_type(const ObExpectType &expect_type, const char OB_JSON_NULL[2] = {'\0', '\0'}; // binary json null -int ObObjCaster::get_zero_value(const ObObjType expect_type, ObCollationType expect_cs_type, ObObj &zero_obj) +int ObObjCaster::get_zero_value(const ObObjType expect_type, + ObCollationType expect_cs_type, + int64_t data_len, + ObIAllocator &alloc, + ObObj &zero_obj) { int ret = OB_SUCCESS; ObObjCastParams params; //构造一个空的cast_param对象,适配SET_RES_XXX宏定义 ObCastMode cast_mode = CM_WARN_ON_FAIL; params.warning_ = 1; //将warning code设置为1,避免SET_RES_XXX宏将其当做真实的warning处理 - if (ob_is_string_tc(expect_type) || ob_is_text_tc(expect_type)) { - zero_obj.set_string(expect_type, ""); + if (ob_is_string_tc(expect_type)) { + //zero_obj.set_string(expect_type, ""); + ObString padding_res; + if (ObVarcharType == expect_type) { + zero_obj.set_string(expect_type, ""); + } else if (0 > data_len) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("The length of fix-len string is less than zero", K(ret), K(data_len)); + } else if (OB_FAIL(sql::padding_char_for_cast(data_len, expect_cs_type, alloc, + padding_res))) { + LOG_WARN("padding char failed", K(ret), K(data_len), K(expect_cs_type)); + } else { + zero_obj.set_string(expect_type, padding_res); + } } else if (ob_is_text_tc(expect_type)) { zero_obj.set_lob_value(expect_type, static_cast(NULL), 0); } else if (ob_is_int_tc(expect_type)) { diff --git a/src/share/object/ob_obj_cast.h b/src/share/object/ob_obj_cast.h index 94607dfba4..e5f4bc5bd9 100644 --- a/src/share/object/ob_obj_cast.h +++ b/src/share/object/ob_obj_cast.h @@ -385,7 +385,11 @@ public: const ObObj &in_obj, ObObj &out_obj); static int to_type(const ObObjType expect_type, ObCollationType expect_cs_type, ObCastCtx &cast_ctx, const ObObj &in_obj, ObObj &out_obj); - static int get_zero_value(const ObObjType expect_type, ObCollationType expect_cs_type, ObObj &zero_obj); + static int get_zero_value(const ObObjType expect_type, + ObCollationType expect_cs_type, + int64_t data_len, + ObIAllocator &alloc, + ObObj &zero_obj); static int enumset_to_inner(const ObObjMeta &expect_meta, const ObObj &in_obj, ObObj &out_obj, common::ObIAllocator &allocator, diff --git a/src/sql/engine/dml/ob_dml_service.cpp b/src/sql/engine/dml/ob_dml_service.cpp index 1549002d0e..5b060ae2ae 100644 --- a/src/sql/engine/dml/ob_dml_service.cpp +++ b/src/sql/engine/dml/ob_dml_service.cpp @@ -41,11 +41,12 @@ int ObDMLService::check_row_null(const ObExprPtrIArray &row, ObEvalCtx &eval_ctx, int64_t row_num, const ColContentIArray &column_infos, - bool is_ignore, + const ObDASDMLBaseCtDef &das_ctdef, bool is_single_value, ObTableModifyOp &dml_op) { int ret = OB_SUCCESS; + const bool is_ignore = das_ctdef.is_ignore_; ObSQLSessionInfo *session = NULL; CK(row.count() >= column_infos.count()); if (OB_ISNULL(session = dml_op.get_exec_ctx().get_my_session())) { @@ -73,8 +74,10 @@ int ObDMLService::check_row_null(const ObExprPtrIArray &row, } else if (OB_FAIL(ObObjCaster::get_zero_value( row.at(col_idx)->obj_meta_.get_type(), row.at(col_idx)->obj_meta_.get_collation_type(), + das_ctdef.column_accuracys_.at(col_idx).get_length(), + eval_ctx.exec_ctx_.get_allocator(), zero_obj))) { - LOG_WARN("get column default zero value failed", K(ret), K(column_infos.at(i))); + LOG_WARN("get column default zero value failed", K(ret), K(column_infos.at(i)), K(row.at(col_idx)->max_length_)); } else if (OB_FAIL(ObTextStringResult::ob_convert_obj_temporay_lob(zero_obj, eval_ctx.exec_ctx_.get_allocator()))) { LOG_WARN("convert lob types zero obj failed", K(ret), K(zero_obj)); } else if (OB_FAIL(row_datum.from_obj(zero_obj))) { @@ -596,7 +599,7 @@ int ObDMLService::process_insert_row(const ObInsCtDef &ins_ctdef, dml_op.get_eval_ctx(), ins_rtdef.cur_row_num_, ins_ctdef.column_infos_, - ins_ctdef.das_ctdef_.is_ignore_, + ins_ctdef.das_ctdef_, ins_ctdef.is_single_value_, dml_op))) { LOG_WARN("check row null failed", K(ret)); @@ -812,7 +815,7 @@ int ObDMLService::process_update_row(const ObUpdCtDef &upd_ctdef, dml_op.get_eval_ctx(), upd_rtdef.cur_row_num_, upd_ctdef.assign_columns_, - upd_ctdef.dupd_ctdef_.is_ignore_, + upd_ctdef.dupd_ctdef_, false, dml_op))) { LOG_WARN("check row null failed", K(ret), K(upd_ctdef), K(upd_rtdef)); @@ -1025,7 +1028,11 @@ int ObDMLService::update_row(const ObUpdCtDef &upd_ctdef, } } else if (OB_UNLIKELY(old_tablet_loc != new_tablet_loc)) { //the updated row may be moved across partitions - if (OB_LIKELY(!upd_ctdef.multi_ctdef_->is_enable_row_movement_)) { + if (upd_ctdef.dupd_ctdef_.is_ignore_) { + ret = OB_NOT_SUPPORTED; + LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cross-partition update ignore"); + LOG_WARN("update ignore is not supported in across partition update, it will induce lost data error", K(ret)); + } else if (OB_LIKELY(!upd_ctdef.multi_ctdef_->is_enable_row_movement_)) { ret = OB_ERR_UPD_CAUSE_PART_CHANGE; LOG_WARN("the updated row is moved across partitions", K(ret), KPC(old_tablet_loc), KPC(new_tablet_loc)); diff --git a/src/sql/engine/dml/ob_dml_service.h b/src/sql/engine/dml/ob_dml_service.h index c5b23f9d2d..8b663e469f 100644 --- a/src/sql/engine/dml/ob_dml_service.h +++ b/src/sql/engine/dml/ob_dml_service.h @@ -28,7 +28,7 @@ public: ObEvalCtx &eval_ctx, int64_t row_num, const ColContentIArray &column_infos, - bool is_ignore, + const ObDASDMLBaseCtDef &das_ctdef, bool is_single_value, ObTableModifyOp &dml_op); static int check_column_type(const ExprFixedArray &dml_row, diff --git a/src/sql/engine/pdml/static/ob_px_multi_part_insert_op.cpp b/src/sql/engine/pdml/static/ob_px_multi_part_insert_op.cpp index a0fd252048..a03a034208 100644 --- a/src/sql/engine/pdml/static/ob_px_multi_part_insert_op.cpp +++ b/src/sql/engine/pdml/static/ob_px_multi_part_insert_op.cpp @@ -133,7 +133,7 @@ int ObPxMultiPartInsertOp::process_row() eval_ctx_, ins_rtdef_.cur_row_num_, MY_SPEC.ins_ctdef_.column_infos_, - MY_SPEC.is_ignore_, + MY_SPEC.ins_ctdef_.das_ctdef_, MY_SPEC.ins_ctdef_.is_single_value_, *this)); OZ(ObDMLService::filter_row_for_view_check(MY_SPEC.ins_ctdef_.view_check_exprs_, eval_ctx_, is_filtered));