[CP] Improve incorrect value error info for insert/replace into values

This commit is contained in:
obdev
2023-08-25 06:10:27 +00:00
committed by ob-robot
parent f78f3aa8a3
commit 233189cbb1
12 changed files with 114 additions and 64 deletions

View File

@ -19,6 +19,7 @@
#include "sql/engine/expr/ob_expr_type_to_str.h"
#include "sql/engine/px/ob_dfo.h"
#include "sql/engine/expr/ob_expr_lob_utils.h"
#include "sql/engine/dml/ob_dml_service.h"
namespace oceanbase
{
@ -81,6 +82,7 @@ int ObExprValuesSpec::serialize(char *buf,
OB_UNIS_ENCODE(err_log_ct_def_);
OB_UNIS_ENCODE(contain_ab_param_);
OB_UNIS_ENCODE(ins_values_batch_opt_);
OB_UNIS_ENCODE(column_names_);
}
}
@ -104,6 +106,7 @@ OB_DEF_SERIALIZE_SIZE(ObExprValuesSpec)
OB_UNIS_ADD_LEN(err_log_ct_def_);
OB_UNIS_ADD_LEN(contain_ab_param_);
OB_UNIS_ADD_LEN(ins_values_batch_opt_);
OB_UNIS_ADD_LEN(column_names_);
return len;
}
@ -116,6 +119,7 @@ OB_DEF_SERIALIZE(ObExprValuesSpec)
OB_UNIS_ENCODE(err_log_ct_def_);
OB_UNIS_ENCODE(contain_ab_param_);
OB_UNIS_ENCODE(ins_values_batch_opt_);
OB_UNIS_ENCODE(column_names_);
return ret;
}
@ -128,6 +132,7 @@ OB_DEF_DESERIALIZE(ObExprValuesSpec)
OB_UNIS_DECODE(err_log_ct_def_);
OB_UNIS_DECODE(contain_ab_param_);
OB_UNIS_DECODE(ins_values_batch_opt_);
OB_UNIS_DECODE(column_names_);
return ret;
}
@ -174,7 +179,7 @@ int64_t ObExprValuesSpec::get_serialize_size_(const ObPhyOpSeriCtx &seri_ctx) co
OB_UNIS_ADD_LEN(err_log_ct_def_);
OB_UNIS_ADD_LEN(contain_ab_param_);
OB_UNIS_ADD_LEN(ins_values_batch_opt_);
OB_UNIS_ADD_LEN(column_names_);
return len;
}
@ -447,6 +452,7 @@ OB_INLINE int ObExprValuesOp::calc_next_row()
}
while (OB_SUCC(ret) && node_idx_ < real_value_cnt && !is_break) {
int64_t real_node_idx = node_idx_ % MY_SPEC.get_value_count();
int64_t row_num = real_node_idx / col_num + 1;
ObExpr *src_expr = MY_SPEC.values_.at(real_node_idx);
ObExpr *dst_expr = MY_SPEC.output_.at(col_idx);
ObDatumMeta src_meta = src_expr->datum_meta_;
@ -547,6 +553,8 @@ OB_INLINE int ObExprValuesOp::calc_next_row()
if (OB_FAIL(datum_caster_.to_type(dst_expr->datum_meta_, str_values,
real_src_expr, cm_, datum))) {
LOG_WARN("fail to do to_type", K(ret), K(*dst_expr), K(real_src_expr));
ObString column_name = MY_SPEC.column_names_.at(col_idx);
ret = ObDMLService::log_user_error_inner(ret, row_num, column_name, ctx_);
}
}
} else if (!dst_expr->obj_meta_.is_lob_storage()) {
@ -558,6 +566,8 @@ OB_INLINE int ObExprValuesOp::calc_next_row()
ret = OB_ERR_CANT_CREATE_GEOMETRY_OBJECT;
LOG_USER_WARN(OB_ERR_CANT_CREATE_GEOMETRY_OBJECT);
}
ObString column_name = MY_SPEC.column_names_.at(col_idx);
ret = ObDMLService::log_user_error_inner(ret, row_num, column_name, ctx_);
}
} else { // dst type is lob
if (OB_FAIL(eval_values_op_dynamic_cast_to_lob(real_src_expr, src_obj_meta, dst_expr))) {

View File

@ -31,6 +31,7 @@ public:
ObExprValuesSpec(common::ObIAllocator &alloc, const ObPhyOperatorType type)
: ObOpSpec(alloc, type),
values_(alloc),
column_names_(alloc),
is_strict_json_desc_(alloc),
str_values_array_(alloc),
err_log_ct_def_(alloc),
@ -50,6 +51,7 @@ private:
DISALLOW_COPY_AND_ASSIGN(ObExprValuesSpec);
public:
common::ObFixedArray<ObExpr *, common::ObIAllocator> values_;
common::ObFixedArray<common::ObString, common::ObIAllocator> column_names_;
common::ObFixedArray<bool, common::ObIAllocator> is_strict_json_desc_;
common::ObFixedArray<ObStrValues, common::ObIAllocator> str_values_array_;
ObErrLogCtDef err_log_ct_def_;

View File

@ -58,7 +58,8 @@ int ObDMLService::check_row_null(const ObExprPtrIArray &row,
const bool is_nullable = column_infos.at(i).is_nullable_;
uint64_t col_idx = column_infos.at(i).projector_index_;
if (OB_FAIL(row.at(col_idx)->eval(eval_ctx, datum))) {
dml_op.log_user_error_inner(ret, row_num, column_infos.at(i));
common::ObString column_name = column_infos.at(i).column_name_;
ret = ObDMLService::log_user_error_inner(ret, row_num, column_name, dml_op.get_exec_ctx());
} else if (!is_nullable && datum->is_null()) {
if (is_ignore ||
(lib::is_mysql_mode() && !is_single_value && !is_strict_mode(session->get_sql_mode()))) {
@ -118,7 +119,8 @@ int ObDMLService::check_column_type(const ExprFixedArray &dml_row,
ObExpr *expr = dml_row.at(column_info.projector_index_);
ObDatum *datum = nullptr;
if (OB_FAIL(expr->eval(dml_op.get_eval_ctx(), datum))) {
dml_op.log_user_error_inner(ret, row_num, column_info);
common::ObString column_name = column_infos.at(i).column_name_;
ret = ObDMLService::log_user_error_inner(ret, row_num, column_name, dml_op.get_exec_ctx());
} else if (!datum->is_null() && expr->obj_meta_.is_geometry()) {
// geo column type
const uint32_t column_srid = column_info.srs_info_.srid_;
@ -2198,5 +2200,82 @@ int ObDMLService::handle_after_row_processing(bool execute_single_row, ObDMLModi
}
return ret;
}
int ObDMLService::log_user_error_inner(
int ret,
int64_t row_num,
common::ObString &column_name,
ObExecContext &ctx)
{
if (OB_DATA_OUT_OF_RANGE == ret) {
ObSQLUtils::copy_and_convert_string_charset(
ctx.get_allocator(),
column_name,
column_name,
CS_TYPE_UTF8MB4_BIN,
ctx.get_my_session()->get_local_collation_connection());
LOG_USER_ERROR(OB_DATA_OUT_OF_RANGE, column_name.length(), column_name.ptr(), row_num);
} else if (OB_ERR_DATA_TOO_LONG == ret && lib::is_mysql_mode()) {
ObSQLUtils::copy_and_convert_string_charset(
ctx.get_allocator(),
column_name,
column_name,
CS_TYPE_UTF8MB4_BIN,
ctx.get_my_session()->get_local_collation_connection());
LOG_USER_ERROR(OB_ERR_DATA_TOO_LONG, column_name.length(), column_name.ptr(), row_num);
} else if (OB_ERR_VALUE_LARGER_THAN_ALLOWED == ret) {
LOG_USER_ERROR(OB_ERR_VALUE_LARGER_THAN_ALLOWED);
} else if (OB_INVALID_DATE_VALUE == ret || OB_INVALID_DATE_FORMAT == ret) {
ret = OB_INVALID_DATE_VALUE;
ObSQLUtils::copy_and_convert_string_charset(
ctx.get_allocator(),
column_name,
column_name,
CS_TYPE_UTF8MB4_BIN,
ctx.get_my_session()->get_local_collation_connection());
LOG_USER_ERROR(
OB_ERR_INVALID_DATE_MSG_FMT_V2,
column_name.length(),
column_name.ptr(),
row_num);
} else if ((OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD == ret || OB_INVALID_NUMERIC == ret)
&& lib::is_mysql_mode()) {
ret = OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD;
ObSQLUtils::copy_and_convert_string_charset(
ctx.get_allocator(),
column_name,
column_name,
CS_TYPE_UTF8MB4_BIN,
ctx.get_my_session()->get_local_collation_connection());
LOG_USER_ERROR(
OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD,
column_name.length(),
column_name.ptr(),
row_num);
} else if (OB_ERR_WARN_DATA_OUT_OF_RANGE == ret && lib::is_mysql_mode()) {
ObSQLUtils::copy_and_convert_string_charset(
ctx.get_allocator(),
column_name,
column_name,
CS_TYPE_UTF8MB4_BIN,
ctx.get_my_session()->get_local_collation_connection());
LOG_USER_ERROR(OB_ERR_WARN_DATA_OUT_OF_RANGE, column_name.length(), column_name.ptr(), row_num);
} else if ((OB_ERR_DATA_TRUNCATED == ret || OB_ERR_DOUBLE_TRUNCATED == ret)
&& lib::is_mysql_mode()) {
ret = OB_ERR_DATA_TRUNCATED;
ob_reset_tsi_warning_buffer();
ObSQLUtils::copy_and_convert_string_charset(
ctx.get_allocator(),
column_name,
column_name,
CS_TYPE_UTF8MB4_BIN,
ctx.get_my_session()->get_local_collation_connection());
LOG_USER_ERROR(OB_ERR_DATA_TRUNCATED, column_name.length(), column_name.ptr(), row_num);
} else {
LOG_WARN("fail to operate row", K(ret));
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -235,6 +235,10 @@ public:
static int add_trans_info_datum(ObExpr *trans_info_expr,
ObEvalCtx &eval_ctx,
ObChunkDatumStore::StoredRow *stored_row);
static int log_user_error_inner(int ret,
int64_t row_num,
common::ObString &column_name,
ObExecContext &ctx);
private:
template <int N>

View File

@ -1017,56 +1017,6 @@ OperatorOpenOrder ObTableModifyOp::get_operator_open_order() const
return open_order;
}
void ObTableModifyOp::log_user_error_inner(int ret, int64_t col_idx, int64_t row_num,
const ObIArray<ColumnContent> &column_infos) const
{
if (OB_DATA_OUT_OF_RANGE == ret &&
(0 <= col_idx && col_idx < column_infos.count())) {
ObString column_name = column_infos.at(col_idx).column_name_;
LOG_USER_ERROR(OB_DATA_OUT_OF_RANGE, column_name.length(), column_name.ptr(), row_num);
} else if (OB_ERR_DATA_TOO_LONG == ret &&
(0 <= col_idx && col_idx < column_infos.count())) {
ObString column_name = column_infos.at(col_idx).column_name_;
if (lib::is_mysql_mode()) {
//for error code OB_ERR_DATA_TOO_LONG, oracle and mysql has the different error msg
//oracle error msg has output in ObExprColumnConv, so need to skip oracle mode here
LOG_USER_ERROR(OB_ERR_DATA_TOO_LONG, column_name.length(), column_name.ptr(), row_num);
}
} else if (OB_ERR_VALUE_LARGER_THAN_ALLOWED == ret && col_idx >= 0) {
LOG_USER_ERROR(OB_ERR_VALUE_LARGER_THAN_ALLOWED);
} else if ((OB_INVALID_DATE_VALUE == ret || OB_INVALID_DATE_FORMAT == ret)
&& (0 <= col_idx && col_idx < column_infos.count())) {
ObString column_name = column_infos.at(col_idx).column_name_;
LOG_USER_ERROR(OB_ERR_INVALID_DATE_MSG_FMT_V2, column_name.length(),
column_name.ptr(), row_num);
} else {
LOG_WARN("fail to operate row", K(ret));
}
}
void ObTableModifyOp::log_user_error_inner(int ret, int64_t row_num, const ColumnContent &column_info) const
{
if (OB_DATA_OUT_OF_RANGE == ret) {
ObString column_name = column_info.column_name_;
LOG_USER_ERROR(OB_DATA_OUT_OF_RANGE, column_name.length(), column_name.ptr(), row_num);
} else if (OB_ERR_DATA_TOO_LONG == ret) {
ObString column_name = column_info.column_name_;
if (lib::is_mysql_mode()) {
//for error code OB_ERR_DATA_TOO_LONG, oracle and mysql has the different error msg
//oracle error msg has output in ObExprColumnConv, so need to skip oracle mode here
LOG_USER_ERROR(OB_ERR_DATA_TOO_LONG, column_name.length(), column_name.ptr(), row_num);
}
} else if (OB_ERR_VALUE_LARGER_THAN_ALLOWED == ret) {
LOG_USER_ERROR(OB_ERR_VALUE_LARGER_THAN_ALLOWED);
} else if (OB_INVALID_DATE_VALUE == ret || OB_INVALID_DATE_FORMAT == ret) {
ObString column_name = column_info.column_name_;
LOG_USER_ERROR(OB_ERR_INVALID_DATE_MSG_FMT_V2, column_name.length(),
column_name.ptr(), row_num);
} else {
LOG_WARN("fail to operate row", K(ret));
}
}
int ObTableModifyOp::submit_all_dml_task()
{
int ret = OB_SUCCESS;

View File

@ -210,9 +210,6 @@ public:
bool is_fk_root_session();
const ObObjPrintParams &get_obj_print_params() { return obj_print_params_; }
int init_foreign_key_operation();
void log_user_error_inner(int ret, int64_t col_idx, int64_t row_num,
const ObIArray<ColumnContent> &column_infos) const;
void log_user_error_inner(int ret, int64_t row_num, const ColumnContent &column_info) const;
void clear_dml_evaluated_flag();
void clear_dml_evaluated_flag(int64_t parent_cnt, ObExpr **parent_exprs);
void clear_dml_evaluated_flag(ObExpr *clear_expr);