diff --git a/src/sql/parser/sql_parser_mysql_mode.y b/src/sql/parser/sql_parser_mysql_mode.y index 9217d3d863..6baf403dce 100644 --- a/src/sql/parser/sql_parser_mysql_mode.y +++ b/src/sql/parser/sql_parser_mysql_mode.y @@ -8853,8 +8853,7 @@ value_or_values insert_vals_list opt_insert_row_alias ParseNode *values_node = NULL; ParseNode *values_list_node = NULL; if ($2->type_ == T_LINK_NODE) { - $2->type_ = T_VALUES_ROW_LIST; - values_list_node = $2; + merge_nodes(values_list_node,result, T_VALUES_ROW_LIST, $2); } else { malloc_non_terminal_node(values_list_node, result->malloc_pool_, T_VALUES_ROW_LIST, 1, $2); } diff --git a/src/sql/resolver/dml/ob_default_value_utils.cpp b/src/sql/resolver/dml/ob_default_value_utils.cpp index fdd6b07f1c..702a7795b2 100644 --- a/src/sql/resolver/dml/ob_default_value_utils.cpp +++ b/src/sql/resolver/dml/ob_default_value_utils.cpp @@ -30,9 +30,11 @@ int ObDefaultValueUtils::generate_insert_value(const ColumnItem *column, { int ret = OB_SUCCESS; ObDMLDefaultOp op = OB_INVALID_DEFAULT_OP; - if (OB_ISNULL(column)) { + if (OB_ISNULL(column) || OB_ISNULL(params_) || + OB_ISNULL(params_->expr_factory_) || + OB_ISNULL(params_->session_info_)) { ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid argument", K(column)); + LOG_WARN("invalid argument", K(column), K(params_), K(params_->expr_factory_), K(params_->session_info_)); } else if (OB_FAIL(get_default_type_for_insert(column, op))) { LOG_WARN("fail to check column default value", K(column), K(ret)); } else if (has_instead_of_trigger diff --git a/src/sql/resolver/dml/ob_del_upd_resolver.cpp b/src/sql/resolver/dml/ob_del_upd_resolver.cpp index c79b68c257..243a4523b3 100644 --- a/src/sql/resolver/dml/ob_del_upd_resolver.cpp +++ b/src/sql/resolver/dml/ob_del_upd_resolver.cpp @@ -86,7 +86,8 @@ ObDelUpdResolver::ObDelUpdResolver(ObResolverParams ¶ms) insert_column_ids_(), is_column_specify_(false), is_oracle_tmp_table_(false), - oracle_tmp_table_type_(0) + oracle_tmp_table_type_(0), + is_resolve_insert_update_(false) { // TODO Auto-generated constructor stub } diff --git a/src/sql/resolver/dml/ob_del_upd_resolver.h b/src/sql/resolver/dml/ob_del_upd_resolver.h index 5e0c9b793a..2f3b718d8d 100644 --- a/src/sql/resolver/dml/ob_del_upd_resolver.h +++ b/src/sql/resolver/dml/ob_del_upd_resolver.h @@ -50,7 +50,7 @@ public: //set is json constraint type is strict or relax const static uint8_t IS_JSON_CONSTRAINT_RELAX = 1; const static uint8_t IS_JSON_CONSTRAINT_STRICT = 4; - + inline bool is_resolve_insert_update() { return is_resolve_insert_update_;} protected: int resolve_assignments(const ParseNode &parse_node, @@ -259,6 +259,8 @@ private: bool is_column_specify_; bool is_oracle_tmp_table_; //是否创建oracle的临时表 int64_t oracle_tmp_table_type_; +protected: + bool is_resolve_insert_update_; }; } /* namespace sql */ diff --git a/src/sql/resolver/dml/ob_dml_resolver.cpp b/src/sql/resolver/dml/ob_dml_resolver.cpp index 1078755570..5f79b06fd9 100755 --- a/src/sql/resolver/dml/ob_dml_resolver.cpp +++ b/src/sql/resolver/dml/ob_dml_resolver.cpp @@ -4375,6 +4375,9 @@ int ObDMLResolver::resolve_generate_table(const ParseNode &table_node, select_resolver.set_current_level(current_level_); select_resolver.set_current_view_level(current_view_level_); select_resolver.set_parent_namespace_resolver(parent_namespace_resolver_); + if (upper_insert_resolver_ != NULL && upper_insert_resolver_->is_mock_for_row_alias()) { + select_resolver.set_upper_insert_resolver(upper_insert_resolver_); + } if (OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null", K(ret)); @@ -7320,7 +7323,7 @@ int ObDMLResolver::try_add_padding_expr_for_column_conv(const ColumnItem *column if (OB_SUCC(ret)) { ObRawExpr *&ori_child = expr->get_param_expr(4); ObRawExpr *real_child = NULL; - OZ(ObRawExprUtils::erase_inner_added_exprs(ori_child, real_child)); + OZ(ObRawExprUtils::erase_inner_cast_exprs(ori_child, real_child)); CK(OB_NOT_NULL(real_child)); if (OB_SUCC(ret) && real_child->get_expr_type() != T_FUN_PAD && real_child->get_expr_type() != T_FUN_INNER_TRIM) { @@ -15655,6 +15658,7 @@ int ObDMLResolver::resolve_values_table_item(const ParseNode &table_node, TableI ParseNode *alias_node = NULL; ObString alias_name; uint64_t data_version = 0; + bool is_mock = (upper_insert_resolver_ != NULL && upper_insert_resolver_->is_mock_for_row_alias()); if (OB_ISNULL(dml_stmt) || OB_ISNULL(allocator_) || OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null", K(ret)); @@ -15678,14 +15682,24 @@ int ObDMLResolver::resolve_values_table_item(const ParseNode &table_node, TableI int64_t column_cnt = 0; ObSEArray res_types; //common values table: values row(...), row(...),... - if (upper_insert_resolver_ == NULL && + /* + 1.upper_insert_resolver_ != NULL && !is_mock + ->insert values table: insert into ....values row(...), row(...),... + 2. upper_insert_resolver_ == NULL + ->select * from (values row(...), row(...)) + 3.is_mock + ->insert into ....values (...,...) as alias on duplicate key set ... + ->insert into ....select * from (values table) as alias on ... + is_mock use to resolve the generated values table + */ + if ((upper_insert_resolver_ == NULL || is_mock) && OB_FAIL(resolve_table_values_for_select(table_node, new_table_item->table_values_, res_types, column_cnt))) { LOG_WARN("failed to resolve table values for select", K(ret)); //insert values table: insert into ....values row(...), row(...),... - } else if (upper_insert_resolver_ != NULL && + } else if (upper_insert_resolver_ != NULL && !is_mock && OB_FAIL(resolve_table_values_for_insert(table_node, new_table_item->table_values_, res_types, @@ -15719,6 +15733,9 @@ int ObDMLResolver::resolve_table_values_for_select(const ParseNode &table_node, const ParseNode *values_node = NULL; ObSEArray value_idxs; column_cnt = 0; + ObInsertStmt *insert_stmt = NULL; + bool is_mock_for_row_alias = (upper_insert_resolver_!= NULL && + upper_insert_resolver_->is_mock_for_row_alias()); if (OB_UNLIKELY(T_VALUES_TABLE_EXPRESSION != table_node.type_ || 1 != table_node.num_child_) || OB_ISNULL(table_node.children_) || OB_ISNULL(values_node = table_node.children_[0]) || OB_UNLIKELY(T_VALUES_ROW_LIST != values_node->type_) || @@ -15734,7 +15751,8 @@ int ObDMLResolver::resolve_table_values_for_select(const ParseNode &table_node, OB_UNLIKELY(T_VALUE_VECTOR != vector_node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid node children", K(i), K(vector_node), K(ret)); - } else if (OB_UNLIKELY(vector_node->num_child_ > common::OB_USER_ROW_MAX_COLUMNS_COUNT)) { + } else if (OB_UNLIKELY(vector_node->num_child_ > common::OB_USER_ROW_MAX_COLUMNS_COUNT) && + !is_mock_for_row_alias) { ret = OB_ERR_TOO_MANY_COLUMNS; LOG_WARN("too many columns", K(ret)); } else { @@ -15763,8 +15781,37 @@ int ObDMLResolver::resolve_table_values_for_select(const ParseNode &table_node, ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to resolve sql expr", K(ret), K(expr)); } else if (expr->get_expr_type() == T_DEFAULT) { - ret = OB_ERR_VALUES_CLAUSE_CANNOT_USE_DEFAULT_VALUES; - LOG_WARN("A VALUES clause cannot use DEFAULT values, unless used as a source in an INSERT statement.", K(ret)); + if (is_mock_for_row_alias) { + insert_stmt = upper_insert_resolver_->get_insert_stmt(); + ObInsertTableInfo &table_info = insert_stmt->get_insert_table_info(); + ColumnItem *column_item = NULL; + uint64_t column_id = table_info.values_desc_.at(j)->get_column_id(); + if (OB_ISNULL(column_item = insert_stmt->get_column_item_by_id(table_info.table_id_, + column_id))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get column item by id failed", K(table_info.table_id_), K(column_id), K(ret)); + } else if (table_info.values_desc_.at(j)->is_generated_column()) { + if (OB_FAIL(copy_schema_expr(*params_.expr_factory_, + column_item->expr_->get_dependant_expr(), + expr))) { + LOG_WARN("copy expr failed", K(ret)); + } else if (expr->has_flag(CNT_COLUMN)) { + if (OB_FAIL(replace_column_ref(cur_values_vector, table_info.values_desc_, expr))) { + LOG_WARN("replace column reference failed", K(ret)); + } else { + LOG_TRACE("succeed to replace column ref", KPC(expr), K(cur_values_vector), K(table_info.values_desc_)); + } + } + } else { + ObDefaultValueUtils utils(insert_stmt, ¶ms_, upper_insert_resolver_); + if (OB_FAIL(utils.resolve_default_expr(*column_item, expr, T_INSERT_SCOPE))) { + LOG_WARN("fail to resolve default value", "table_id", table_info.table_id_, K(column_id), K(ret)); + } + } + } else { + ret = OB_ERR_VALUES_CLAUSE_CANNOT_USE_DEFAULT_VALUES; + LOG_WARN("A VALUES clause cannot use DEFAULT values, unless used as a source in an INSERT statement.", K(ret)); + } } if (OB_SUCC(ret)) { if (OB_ISNULL(expr)) { diff --git a/src/sql/resolver/dml/ob_insert_resolver.cpp b/src/sql/resolver/dml/ob_insert_resolver.cpp index 4cc167bad7..e97dd03eb2 100644 --- a/src/sql/resolver/dml/ob_insert_resolver.cpp +++ b/src/sql/resolver/dml/ob_insert_resolver.cpp @@ -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 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 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(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(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(col_ref_node->children_[2]->str_len_)); + static_cast(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 &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)); } diff --git a/src/sql/resolver/dml/ob_insert_resolver.h b/src/sql/resolver/dml/ob_insert_resolver.h index 51a369eaf6..dab0c50594 100644 --- a/src/sql/resolver/dml/ob_insert_resolver.h +++ b/src/sql/resolver/dml/ob_insert_resolver.h @@ -54,6 +54,7 @@ public: { return static_cast(stmt_); } + bool is_mock_for_row_alias() {return is_mock_;} protected: int process_values_function(ObRawExpr *&expr) override; virtual int mock_values_column_ref(const ObColumnRefRawExpr *column_ref) override; @@ -93,6 +94,8 @@ private: int check_ambiguous_column(ObString &column_name, ObIArray &ori_column_names, ObIArray &row_alias_column_names); + bool find_in_column(ObString &column_name, + ObIArray &column_names); virtual int resolve_insert_update_assignment(const ParseNode *node, ObInsertTableInfo& table_info) override; int replace_column_to_default(ObRawExpr *&origin); virtual int check_returning_validity() override; @@ -115,6 +118,7 @@ private: int64_t row_count_; ObSelectResolver *sub_select_resolver_; bool autoinc_col_added_; + bool is_mock_; }; } // namespace sql } // namespace oceanbase diff --git a/src/sql/resolver/dml/ob_select_resolver.cpp b/src/sql/resolver/dml/ob_select_resolver.cpp index 734e8d131b..f42981a5c4 100644 --- a/src/sql/resolver/dml/ob_select_resolver.cpp +++ b/src/sql/resolver/dml/ob_select_resolver.cpp @@ -12,6 +12,7 @@ #define USING_LOG_PREFIX SQL_RESV #include "sql/resolver/dml/ob_select_resolver.h" +#include "sql/resolver/dml/ob_del_upd_resolver.h" #include "lib/oblog/ob_log_module.h" #include "lib/json/ob_json_print_utils.h" // for SJ #include "lib/time/ob_time_utility.h" @@ -4927,9 +4928,18 @@ int ObSelectResolver::resolve_column_ref_in_all_namespace( //for insert into t1 values((select c1 from dual)) ==> can't check column c1 in t1; if (cur_resolver->get_basic_stmt() != NULL && cur_resolver->get_basic_stmt()->is_insert_stmt()) { - //do nothing + //INSERT INTO t0 values (1,10) ON DUPLICATE KEY UPDATE b = (SELECT y FROM t1 WHERE x = values(a)); + // ==> should check column a in duplicate key update; + if (static_cast(cur_resolver)->is_resolve_insert_update()) { + if (OB_FAIL(cur_resolver->resolve_column_ref_expr(q_name, real_ref_expr))) { + LOG_WARN_IGNORE_COL_NOTFOUND(ret, "resolve column ref failed", K(ret), K(q_name)); + } + } } else if (OB_FAIL(cur_resolver->resolve_column_ref_for_subquery(q_name, real_ref_expr))) { LOG_WARN_IGNORE_COL_NOTFOUND(ret, "resolve column for subquery failed", K(ret), K(q_name)); + } + if (OB_FAIL(ret)) { + //do nothing } else if (OB_ISNULL(query_ref = cur_resolver->get_subquery())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("no subquery is found", K(ret)); diff --git a/src/sql/resolver/expr/ob_raw_expr_util.cpp b/src/sql/resolver/expr/ob_raw_expr_util.cpp index d0cd343156..aec2dd5738 100644 --- a/src/sql/resolver/expr/ob_raw_expr_util.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_util.cpp @@ -4215,6 +4215,19 @@ int ObRawExprUtils::erase_inner_added_exprs(ObRawExpr *src_expr, ObRawExpr *&out return ret; } +int ObRawExprUtils::erase_inner_cast_exprs(ObRawExpr *src_expr, ObRawExpr *&out_expr) +{ + int ret = OB_SUCCESS; + CK(OB_NOT_NULL(src_expr)); + OX(out_expr = src_expr); + if (OB_SUCC(ret) && src_expr->has_flag(IS_INNER_ADDED_EXPR) && + T_FUN_SYS_CAST == src_expr->get_expr_type()) { + CK(2 == src_expr->get_param_count()); + OZ(erase_inner_added_exprs(src_expr->get_param_expr(0), out_expr)); + } + return ret; +} + int ObRawExprUtils::erase_operand_implicit_cast(ObRawExpr *src, ObRawExpr *&out) { int ret = OB_SUCCESS; diff --git a/src/sql/resolver/expr/ob_raw_expr_util.h b/src/sql/resolver/expr/ob_raw_expr_util.h index da2d06578f..96f848bffd 100644 --- a/src/sql/resolver/expr/ob_raw_expr_util.h +++ b/src/sql/resolver/expr/ob_raw_expr_util.h @@ -496,6 +496,7 @@ public: ObExprResType &utf8_type); static int erase_inner_added_exprs(ObRawExpr *src_expr, ObRawExpr *&out_expr); + static int erase_inner_cast_exprs(ObRawExpr *src_expr, ObRawExpr *&out_expr); // erase implicit cast which added for operand casting. static int erase_operand_implicit_cast(ObRawExpr *src, ObRawExpr *&out);