[CP] duplicate updat bug修复
This commit is contained in:
@ -43,7 +43,8 @@ ObInsertResolver::ObInsertResolver(ObResolverParams ¶ms)
|
||||
: 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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user