[CP] duplicate updat bug修复

This commit is contained in:
akaError
2024-02-10 08:22:06 +00:00
committed by ob-robot
parent 43c547ebdb
commit e4a0de2d29
10 changed files with 147 additions and 23 deletions

View File

@ -43,7 +43,8 @@ ObInsertResolver::ObInsertResolver(ObResolverParams &params)
: ObDelUpdResolver(params),
row_count_(0),
sub_select_resolver_(NULL),
autoinc_col_added_(false)
autoinc_col_added_(false),
is_mock_(false)
{
params.contain_dml_ = true;
}
@ -278,6 +279,10 @@ int ObInsertResolver::process_values_function(ObRawExpr *&expr)
uint64_t column_id = b_expr->get_column_id();
ColumnItem *column_item = NULL;
if (OB_ISNULL(column_item = insert_stmt->get_column_item_by_id(table_id, column_id))) {
ret = OB_ERR_BAD_FIELD_ERROR;
ObString scope_name = ObString::make_string(get_scope_name(current_scope_));
LOG_USER_ERROR(OB_ERR_BAD_FIELD_ERROR, b_expr->get_column_name().length(), b_expr->get_column_name().ptr(),
scope_name.length(), scope_name.ptr());
LOG_WARN("fail to get column item", K(ret), K(table_id), K(column_id));
} else {
const int64_t N = insert_columns.count();
@ -304,6 +309,19 @@ int ObInsertResolver::process_values_function(ObRawExpr *&expr)
T_INSERT_SCOPE,
true))) {
LOG_WARN("fail to add additional function", K(ret));
} else if (value_expr->is_const_expr() &&
!ob_is_enum_or_set_type(value_expr->get_data_type())) {
ObRawExpr* remove_const_expr = NULL;
if (OB_FAIL(ObRawExprUtils::build_remove_const_expr(*params_.expr_factory_,
*params_.session_info_,
value_expr, remove_const_expr))) {
LOG_WARN("fail to build remove_const expr",K(ret), K(expr), K(remove_const_expr));
} else {
value_expr = remove_const_expr;
}
}
if (OB_FAIL(ret)) {
//do nothing
} else if (OB_FAIL(ObRawExprUtils::replace_ref_column(expr, b_expr, value_expr))) {
LOG_WARN("fail to replace ref column", K(ret), K(b_expr), K(value_expr));
} else {
@ -560,7 +578,7 @@ int ObInsertResolver::resolve_values(const ParseNode &value_node,
LOG_WARN("allocate select buffer failed", K(ret), "size", sizeof(ObSelectResolver));
} else {
// value from sub-query(insert into table select ..)
bool is_mock = lib::is_mysql_mode() && value_node.reserved_;
is_mock_ = lib::is_mysql_mode() && value_node.reserved_;
ObSelectStmt *select_stmt = NULL;
sub_select_resolver_ = new(select_buffer) ObSelectResolver(params_);
//insert clause and select clause in insert into select belong to the same namespace level
@ -576,7 +594,7 @@ int ObInsertResolver::resolve_values(const ParseNode &value_node,
ObSEArray<ColumnItem, 4> column_items;
ParseNode *alias_node = NULL;
ParseNode *table_alias_node = NULL;
if (is_mock &&
if (is_mock_ &&
value_node.children_[PARSE_SELECT_FROM] != NULL &&
value_node.children_[PARSE_SELECT_FROM]->num_child_ == 1 &&
value_node.children_[PARSE_SELECT_FROM]->children_[0]->type_ == T_ALIAS &&
@ -601,7 +619,7 @@ int ObInsertResolver::resolve_values(const ParseNode &value_node,
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid select stmt", K(select_stmt));
} else if (!session_info_->get_ddl_info().is_ddl() &&
OB_FAIL(check_insert_select_field(*insert_stmt, *select_stmt, is_mock))) {
OB_FAIL(check_insert_select_field(*insert_stmt, *select_stmt, is_mock_))) {
LOG_WARN("check insert select field failed", K(ret), KPC(insert_stmt), KPC(select_stmt));
} else if (!session_info_->get_ddl_info().is_ddl() && OB_FAIL(add_new_sel_item_for_oracle_temp_table(*select_stmt))) {
LOG_WARN("add session id value to select item failed", K(ret));
@ -613,7 +631,7 @@ int ObInsertResolver::resolve_values(const ParseNode &value_node,
LOG_WARN("failed to resolve generate table item", K(ret));
}
if (OB_SUCC(ret) && is_mock) {
if (OB_SUCC(ret) && is_mock_) {
ObString ori_table_name = table_item->table_name_;
ObSEArray<ObString, 4> ori_column_names;
ObString row_alias_table_name = sub_select_table->get_table_name();
@ -777,17 +795,28 @@ int ObInsertResolver::check_validity_of_duplicate_node(const ParseNode* node,
//case: insert into t1(a,b) values (4,5) as new(a,b) on duplicate key update a = value(new.a)+new.a;
//new.a under values is not allowed
ParseNode* col_ref_node = expr_list_node->children_[i];
if (col_ref_node->num_child_ != 3) {
if (col_ref_node->num_child_ != 3 || OB_ISNULL(col_ref_node->children_[2])) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected error", K(ret));
LOG_WARN("unexpected error", K(col_ref_node->num_child_), K(col_ref_node->children_[2]), K(ret));
} else if (col_ref_node->children_[1] == NULL) {
//do nothing
//table node is null
//insert into t1(a,b) values (4,5) as new(a,b) on duplicate key update a = value(a)+a
//a in valus expr must be column of target table t1
node_column_name.assign_ptr(col_ref_node->children_[2]->str_value_,
static_cast<int32_t>(col_ref_node->children_[2]->str_len_));
if (!find_in_column(node_column_name, ori_column_names)) {
ret = OB_ERR_BAD_FIELD_ERROR;
ObString scope_name = ObString::make_string(get_scope_name(current_scope_));
LOG_USER_ERROR(OB_ERR_BAD_FIELD_ERROR, node_column_name.length(), node_column_name.ptr(),
scope_name.length(), scope_name.ptr());
}
} else {
//table node is not null
node_table_name.assign_ptr(col_ref_node->children_[1]->str_value_,
static_cast<int32_t>(col_ref_node->children_[1]->str_len_));
if (0 == (node_table_name.compare(row_alias_table_name))) {
node_column_name.assign_ptr(col_ref_node->children_[2]->str_value_,
static_cast<int32_t>(col_ref_node->children_[2]->str_len_));
static_cast<int32_t>(col_ref_node->children_[2]->str_len_));
ret = OB_ERR_BAD_FIELD_ERROR;
ObString scope_name = ObString::make_string(get_scope_name(current_scope_));
LOG_USER_ERROR(OB_ERR_BAD_FIELD_ERROR, node_column_name.length(), node_column_name.ptr(),
@ -797,9 +826,9 @@ int ObInsertResolver::check_validity_of_duplicate_node(const ParseNode* node,
}
}
}
is_valid = false;
}
}
is_valid = false;
} else if (T_COLUMN_REF == node->type_) {
ObString table_name;
ObString column_name;
@ -873,6 +902,20 @@ int ObInsertResolver::check_ambiguous_column(ObString &column_name,
}
return ret;
}
bool ObInsertResolver::find_in_column(ObString &column_name,
ObIArray<ObString> &column_names)
{
bool find_column = false;
for (int i = 0; !find_column && i < column_names.count(); i++) {
ObString tmp_col_name = column_names.at(i);
if (0 == (column_name.case_compare(tmp_col_name))) {
find_column = true;
}
}
return find_column;
}
int ObInsertResolver::check_insert_select_field(ObInsertStmt &insert_stmt,
ObSelectStmt &select_stmt,
bool is_mock)
@ -1151,6 +1194,8 @@ int ObInsertResolver::resolve_insert_update_assignment(const ParseNode *node, Ob
ret = OB_NOT_SUPPORTED;
LOG_WARN("REPLACE statement does not support ON DUPLICATE KEY UPDATE clause");
LOG_USER_ERROR(OB_NOT_SUPPORTED, "REPLACE statement ON DUPLICATE KEY UPDATE clause");
} else if (FALSE_IT(is_resolve_insert_update_ = true)) {
//do nothing
} else if (OB_FAIL(ObDelUpdResolver::resolve_insert_update_assignment(node, table_info))) {
LOG_WARN("resolve assignment error", K(ret));
}