/** * Copyright (c) 2021 OceanBase * OceanBase CE is licensed under Mulan PubL v2. * You can use this software according to the terms and conditions of the Mulan PubL v2. * You may obtain a copy of Mulan PubL v2 at: * http://license.coscl.org.cn/MulanPubL-2.0 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PubL v2 for more details. */ #define USING_LOG_PREFIX SQL_OPT #include "sql/resolver/dml/ob_insert_stmt.h" #include "sql/optimizer/ob_log_insert.h" #include "sql/optimizer/ob_insert_log_plan.h" #include "sql/optimizer/ob_log_operator_factory.h" #include "sql/optimizer/ob_log_plan_factory.h" #include "sql/optimizer/ob_select_log_plan.h" #include "sql/optimizer/ob_log_expr_values.h" #include "sql/optimizer/ob_log_append.h" #include "sql/optimizer/ob_log_group_by.h" #include "sql/optimizer/ob_opt_est_cost.h" #include "sql/optimizer/ob_log_conflict_row_fetcher.h" #include "sql/engine/expr/ob_expr_column_conv.h" #include "sql/optimizer/ob_log_subplan_filter.h" #include "sql/optimizer/ob_log_insert_all.h" using namespace oceanbase; using namespace sql; using namespace oceanbase::common; using namespace oceanbase::sql::log_op_def; int ObInsertLogPlan::generate_plan() { int ret = OB_SUCCESS; ObInsertStmt* insert_stmt = static_cast(get_stmt()); if (OB_ISNULL(insert_stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("insert stmt is null", K(ret)); } else if (OB_FAIL(generate_raw_plan())) { LOG_WARN("failed to generate raw plan", K(ret)); } else if (OB_ISNULL(get_plan_root()) || OB_ISNULL(insert_op_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); } if (OB_SUCC(ret)) { // init multi table assign info const ObTablesAssignments& table_assign = insert_stmt->get_tables_assignments(); ObIArray& table_columns = insert_stmt->get_all_table_columns(); if (!insert_stmt->is_multi_insert_stmt()) { CK(table_columns.count() == 1); } CK(OB_NOT_NULL(optimizer_context_.get_session_info())); if (OB_SUCC(ret) && OB_LIKELY(table_assign.count() == 1)) { if (OB_SUCC(ret) && !table_assign.at(0).assignments_.empty()) { ObConstRawExpr* lock_row_flag_expr = NULL; if (OB_FAIL(ObRawExprUtils::build_var_int_expr(optimizer_context_.get_expr_factory(), lock_row_flag_expr))) { LOG_WARN("fail to create expr", K(ret)); } else if (OB_FAIL(lock_row_flag_expr->formalize(optimizer_context_.get_session_info()))) { LOG_WARN("fail to formalize", K(ret)); } else { insert_op_->set_lock_row_flag_expr(lock_row_flag_expr); } } ObIArray& index_infos = table_columns.at(0).index_dml_infos_; for (int64_t i = 0; OB_SUCC(ret) && i < index_infos.count(); ++i) { LOG_DEBUG("table_assign", K(table_assign.at(0).assignments_)); if (OB_FAIL(index_infos.at(i).init_assignment_info(table_assign.at(0).assignments_))) { LOG_WARN("init index assignment info failed", K(ret)); } else if (optimizer_context_.get_session_info()->use_static_typing_engine()) { if (OB_FAIL(index_infos.at(i).add_spk_assignment_info(optimizer_context_.get_expr_factory()))) { LOG_WARN("fail to add spk assignment info", K(ret)); } } } } } if (OB_FAIL(ret)) { } else if (OB_FAIL(get_plan_root()->adjust_parent_child_relationship())) { LOG_WARN("failed to adjust parent-child relationship", K(ret)); } else if (OB_FAIL(plan_traverse_loop(ALLOC_LINK, ALLOC_EXCH, ALLOC_GI, ADJUST_SORT_OPERATOR, PX_PIPE_BLOCKING, PX_RESCAN, RE_CALC_OP_COST, ALLOC_MONITORING_DUMP, OPERATOR_NUMBERING, EXCHANGE_NUMBERING, ALLOC_EXPR, PROJECT_PRUNING, ALLOC_DUMMY_OUTPUT, CG_PREPARE, GEN_SIGNATURE, GEN_LOCATION_CONSTRAINT, PX_ESTIMATE_SIZE, GEN_LINK_STMT))) { LOG_WARN("failed to do plan traverse", K(ret)); } else if (location_type_ != ObPhyPlanType::OB_PHY_PLAN_UNCERTAIN) { location_type_ = phy_plan_type_; } if (OB_SUCC(ret) && is_self_part_insert()) { if (OB_FAIL(map_value_param_index())) { LOG_WARN("map value param index failed", K(ret)); } } if (OB_SUCC(ret) && insert_op_->is_multi_part_dml()) { if (optimizer_context_.get_session_info()->use_static_typing_engine() && insert_stmt->get_row_count() > 1) { ret = STATIC_ENG_NOT_IMPLEMENT; LOG_WARN("static engine not support multi part dml with multi values, will retry", K(ret)); } if (OB_SUCC(ret)) { if (OB_FAIL(generate_duplicate_key_checker(*insert_op_))) { LOG_WARN("generate duplicae key checker failed", K(ret)); } } } if (OB_SUCC(ret)) { if (OB_FAIL(calc_plan_resource())) { LOG_WARN("fail calc plan resource", K(ret)); } } if (OB_SUCC(ret) && GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_2250 && insert_stmt->is_returning()) { // handle upgrade if (get_phy_plan_type() == OB_PHY_PLAN_UNCERTAIN || get_phy_plan_type() == OB_PHY_PLAN_LOCAL) { // the plan is executed on 2260 server if it is a multi part dml or a local plan } else { // distributed exuecution may involve 2250 server ret = OB_NOT_SUPPORTED; LOG_WARN("returning is not compatible with previous version", K(ret)); } } return ret; } int ObInsertLogPlan::allocate_insert_op(ObInsertStmt& insert_stmt, ObLogInsert*& insert_op) { int ret = OB_SUCCESS; insert_op = static_cast(get_log_op_factory().allocate(*this, LOG_INSERT)); if (OB_ISNULL(insert_op)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate insert operator failed", K(ret)); } else { insert_op->set_all_table_columns(&insert_stmt.get_all_table_columns()); insert_op->set_value_columns(&insert_stmt.get_values_desc()); insert_op->set_column_convert_exprs(&insert_stmt.get_column_conv_functions()); insert_op->set_primary_key_ids(&insert_stmt.get_primary_key_ids()); insert_op->set_replace(insert_stmt.is_replace()); insert_op->set_only_one_unique_key(insert_stmt.is_only_one_unique_key()); insert_op->set_ignore(insert_stmt.is_ignore()); insert_op->set_check_constraint_exprs(&(insert_stmt.get_check_constraint_exprs())); // If assign partitions to scan, set partition hint if (insert_stmt.get_stmt_hint().part_hints_.count() > 0) { insert_op->set_part_hint(insert_stmt.get_stmt_hint().get_part_hint(insert_stmt.get_insert_table_id())); } if (insert_stmt.get_insert_up()) { if (insert_stmt.get_tables_assignments().count() != 1) { ret = OB_ERR_UNEXPECTED; LOG_WARN("Assignment num should be one", K(ret)); } else { insert_op->set_insert_up(true); insert_op->set_all_table_columns(&insert_stmt.get_all_table_columns()); insert_op->set_tables_assignments(&insert_stmt.get_tables_assignments()); } } } return ret; } int ObInsertLogPlan::allocate_insert_all_op(ObInsertStmt& insert_stmt, ObLogInsert*& insert_op) { int ret = OB_SUCCESS; ObLogInsertAll* insert_all_op = static_cast(get_log_op_factory().allocate(*this, LOG_INSERT_ALL)); if (OB_ISNULL(insert_all_op)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate insert operator failed", K(ret)); } else { insert_all_op->set_all_table_columns(&insert_stmt.get_all_table_columns()); insert_all_op->set_is_multi_table_insert(true); insert_all_op->set_is_multi_insert_first(insert_stmt.is_multi_insert_first()); insert_all_op->set_is_multi_conditions_insert(insert_stmt.is_multi_conditions_insert()); insert_all_op->set_multi_value_columns(&insert_stmt.get_multi_values_desc()); insert_all_op->set_multi_column_convert_exprs(&insert_stmt.get_multi_insert_col_conv_funcs()); insert_all_op->set_multi_insert_table_info(&insert_stmt.get_multi_insert_table_info()); // If assign partitions to scan, set partition hint if (insert_stmt.get_stmt_hint().part_hints_.count() > 0) { for (int64_t i = 0; OB_SUCC(ret) && i < insert_stmt.get_all_table_columns().count(); ++i) { const ObPartHint* part_hint = insert_stmt.get_stmt_hint().get_part_hint(insert_stmt.get_insert_table_id(i)); if (part_hint == NULL) { /*do nothing*/ } else if (OB_FAIL(insert_all_op->add_part_hint(part_hint))) { LOG_WARN("failed to add part hint", K(ret)); } else { /*do nothing*/ } } } if (OB_SUCC(ret)) { insert_op = insert_all_op; } } return ret; } int ObInsertLogPlan::allocate_pdml_insert_as_top(ObLogicalOperator*& top_op) { int ret = OB_SUCCESS; ObInsertStmt* stmt = static_cast(get_stmt()); CK(OB_NOT_NULL(stmt)); if (OB_SUCC(ret)) { int64_t dml_op_count = stmt->get_all_table_columns().at(0).index_dml_infos_.count(); ObLogInsert* insert_log_op = nullptr; ObLogicalOperator* values_root = top_op; for (int64_t idx = 0; OB_SUCC(ret) && idx < dml_op_count; ++idx) { const ObIArray* table_columns = NULL; if (OB_ISNULL(insert_log_op = static_cast(log_op_factory_.allocate(*this, LOG_INSERT)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("no memory", K(ret)); } else if (OB_ISNULL(table_columns = stmt->get_slice_from_all_table_columns(allocator_, 0, idx))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("fail to get table column slice", K(ret), K(idx)); } else if (OB_UNLIKELY(table_columns->count() != 1 || table_columns->at(0).index_dml_infos_.count() != 1)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid table_columns", K(ret), KPC(table_columns)); } // fill insert op params if (OB_SUCC(ret)) { insert_log_op->set_all_table_columns(table_columns); insert_log_op->set_value_columns(&stmt->get_values_desc()); insert_log_op->set_column_convert_exprs( &stmt->get_all_table_columns().at(0).index_dml_infos_.at(idx).column_convert_exprs_); insert_log_op->set_primary_key_ids(&stmt->get_primary_key_ids()); insert_log_op->set_replace(stmt->is_replace()); insert_log_op->set_only_one_unique_key(stmt->is_only_one_unique_key()); insert_log_op->set_ignore(stmt->is_ignore()); insert_log_op->set_check_constraint_exprs(&(stmt->get_check_constraint_exprs())); insert_log_op->set_first_dml_op(idx == 0); insert_log_op->set_is_pdml(true); if (idx > 0) { insert_log_op->set_index_maintenance(true); } if (idx == dml_op_count - 1) { insert_log_op->set_is_returning(stmt->is_returning()); insert_log_op->set_pdml_is_returning(stmt->is_returning()); } else { insert_log_op->set_pdml_is_returning(true); } // If assign partitions to scan, set partition hint if (stmt->get_stmt_hint().part_hints_.count() > 0) { insert_log_op->set_part_hint(stmt->get_stmt_hint().get_part_hint(stmt->get_insert_table_id())); } if (stmt->get_insert_up()) { if (stmt->get_tables_assignments().count() != 1) { ret = OB_ERR_UNEXPECTED; LOG_WARN("Assignment num should be one", K(ret)); } else { insert_log_op->set_insert_up(true); insert_log_op->set_all_table_columns(&stmt->get_all_table_columns()); insert_log_op->set_tables_assignments(&stmt->get_tables_assignments()); } } insert_log_op->set_card(values_root->get_card()); insert_log_op->set_op_cost(ObOptEstCost::get_cost_params().CPU_TUPLE_COST * values_root->get_card()); insert_log_op->set_cost(values_root->get_cost() + insert_log_op->get_op_cost()); insert_log_op->set_is_insert_select(stmt->value_from_select()); } if (OB_SUCC(ret)) { insert_log_op->set_child(ObLogicalOperator::first_child, top_op); top_op = insert_log_op; if (OB_FAIL(insert_log_op->compute_property())) { LOG_WARN("fail to compute property", K(ret)); } } } // end for } return ret; } int ObInsertLogPlan::generate_raw_plan() { int ret = OB_SUCCESS; ObInsertStmt* insert_stmt = static_cast(get_stmt()); ObLogicalOperator* top = NULL; if (OB_ISNULL(get_stmt()) || OB_UNLIKELY(!get_stmt()->is_insert_stmt())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("stmt is invalid", K(ret)); } else if (OB_FAIL(set_autoinc_params(insert_stmt->get_autoinc_params()))) { // set auto-increment params LOG_WARN("failed to set auto-increment params", K(ret)); } else { ObLogicalOperator* values_root = NULL; if (!insert_stmt->value_from_select()) { // step. allocate inserted value exprs if (get_stmt()->has_sequence() && OB_FAIL(allocate_sequence_as_top(values_root))) { LOG_WARN("failed to allocate sequence as top", K(ret)); } else if (OB_FAIL(generate_values_op_as_child(values_root))) { LOG_WARN("generate values op as child failed", K(ret)); } else { /*do nothing*/ } } else if (OB_FAIL(generate_plan_tree())) { LOG_WARN("failed to generate plan tree", K(ret)); } else if (OB_FAIL(get_current_best_plan(values_root))) { LOG_WARN("failed to chooose best plan", K(ret)); } // allocate subplan filter for "INSERT .. ON DUPLICATE KEY UPDATE c1 = (select...)" if (OB_SUCC(ret) && insert_stmt->get_insert_up()) { ObSEArray assign_exprs; ObSEArray subqueries; if (OB_FAIL(insert_stmt->get_tables_assignments_exprs(assign_exprs))) { LOG_WARN("failed to get assignment exprs", K(ret)); } else if (OB_FAIL(ObOptimizerUtil::get_subquery_exprs(assign_exprs, subqueries))) { LOG_WARN("failed to get subqueries", K(ret)); } else if (subqueries.empty()) { // do nothing } else if (OB_FAIL(allocate_subplan_filter_as_top(subqueries, false, values_root))) { LOG_WARN("failed to allocate subplan", K(ret)); } } if (OB_SUCC(ret)) { if (optimizer_context_.use_pdml()) { top = values_root; if (OB_FAIL(allocate_pdml_insert_as_top(top))) { LOG_WARN("fail to allocate insert ops", K(ret)); } else { insert_op_ = static_cast(top); } } else { if (insert_stmt->is_multi_insert_stmt()) { if (OB_FAIL(allocate_insert_all_op(*insert_stmt, insert_op_))) { LOG_WARN("allocate logical insert operator failed", K(ret)); } else if (insert_stmt->has_sequence() && OB_FAIL(allocate_sequence_as_top(values_root))) { LOG_WARN("failed to allocate sequence as top", K(ret)); } else { /*do nothing*/ } } else if (OB_FAIL(allocate_insert_op(*insert_stmt, insert_op_))) { LOG_WARN("allocate logical insert operator failed", K(ret)); } if (OB_SUCC(ret)) { insert_op_->set_child(ObLogicalOperator::first_child, values_root); insert_op_->set_card(values_root->get_card()); insert_op_->set_op_cost(ObOptEstCost::get_cost_params().CPU_TUPLE_COST * values_root->get_card()); insert_op_->set_cost(values_root->get_cost() + insert_op_->get_op_cost()); insert_op_->set_is_insert_select(insert_stmt->value_from_select()); insert_op_->set_is_returning(insert_stmt->is_returning()); if (OB_FAIL(insert_op_->extract_value_exprs())) { LOG_WARN("failed to extract value exprs", K(ret)); } else if (OB_FAIL(insert_op_->compute_property())) { LOG_WARN("failed to compute equal set", K(ret)); } else { top = insert_op_; } } } } if (OB_SUCC(ret) && insert_stmt->get_returning_aggr_item_size() > 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("insert stmt should not have single-set aggregate", K(ret)); } if (OB_SUCC(ret)) { if (OB_FAIL(set_final_plan_root(top))) { LOG_WARN("failed to set plan root", K(ret)); } } } return ret; } int ObInsertLogPlan::generate_duplicate_key_checker(ObLogInsert& insert_op) { int ret = OB_SUCCESS; ObLogicalOperator* dupkey_op = NULL; const ObInsertStmt* insert_stmt = static_cast(get_stmt()); if (OB_ISNULL(insert_stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("insert stmt is null"); } else { ObRawExpr* calc_part_expr = NULL; ObLogDupKeyChecker& dupkey_checker = insert_op.get_dupkey_checker(); const ObUniqueConstraintCheckStmt& constraint_stmt = insert_stmt->get_constraint_check_stmt(); dupkey_checker.set_unique_index_cnt(constraint_stmt.constraint_infos_.count()); dupkey_checker.set_constraint_infos(&constraint_stmt.constraint_infos_); if (OB_SUCC(ret)) { const ObIArray& constraint_infos = constraint_stmt.constraint_infos_; for (int64_t i = 0; OB_SUCC(ret) && i < constraint_infos.count(); ++i) { const ObIArray& constraint_columns = constraint_infos.at(i).constraint_columns_; for (int64_t j = 0; OB_SUCC(ret) && j < constraint_columns.count(); ++j) { OZ(get_all_exprs().append(static_cast(constraint_columns.at(j)))); } } } for (int64_t i = 0; OB_SUCC(ret) && i < constraint_stmt.gui_scan_infos_.count(); ++i) { const ObDupKeyScanInfo& dupkey_scan_info = constraint_stmt.gui_scan_infos_.at(i); OZ(generate_dupkey_scan_info(dupkey_scan_info, dupkey_op, calc_part_expr)); OZ(dupkey_checker.add_gui_scan_root(dupkey_op)); OZ(dupkey_checker.add_gui_scan_calc_part_exprs(calc_part_expr)); } if (OB_SUCC(ret) && !constraint_stmt.gui_scan_infos_.empty()) { if (OB_FAIL(generate_dupkey_scan_info(constraint_stmt.gui_lookup_info_, dupkey_op, calc_part_expr))) { LOG_WARN("generate dupkey scan info failed", K(ret)); } else { dupkey_checker.set_gui_lookup_root(dupkey_op); dupkey_checker.set_gui_lookup_calc_part_expr(calc_part_expr); } } if (OB_SUCC(ret)) { const ObDupKeyScanInfo& dupkey_scan_info = constraint_stmt.table_scan_info_; if (OB_FAIL(generate_dupkey_scan_info(dupkey_scan_info, dupkey_op, calc_part_expr))) { LOG_WARN("generate dupkey scan info failed", K(ret)); } else { dupkey_checker.set_table_scan_root(dupkey_op); dupkey_checker.set_tsc_calc_part_expr(calc_part_expr); } } LOG_TRACE("generate duplicate key checker", K(ret), K(dupkey_checker)); } return ret; } int ObInsertLogPlan::generate_dupkey_scan_info( const ObDupKeyScanInfo& dupkey_info, ObLogicalOperator*& dupkey_op, ObRawExpr*& calc_part_expr) { int ret = OB_SUCCESS; ObLogConflictRowFetcher* fetcher_op = NULL; if (OB_ISNULL(fetcher_op = static_cast( get_log_op_factory().allocate(*this, log_op_def::LOG_CONFLICT_ROW_FETCHER)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate log table scan operator", K(ret)); } else if (OB_FAIL(append(fetcher_op->get_conflict_exprs(), dupkey_info.conflict_exprs_))) { LOG_WARN("append conflict expr expr to log conflict row fetcher failed", K(ret), K(dupkey_info)); } else if (OB_FAIL(fetcher_op->get_access_exprs().assign(dupkey_info.access_exprs_))) { LOG_WARN("construct access expr to log conflict row fetcher failed", K(ret)); } else if (OB_FAIL(fetcher_op->get_output_exprs().assign(dupkey_info.output_exprs_))) { LOG_WARN("construct output expr to log conflict row fetcher failed", K(ret)); } else if (OB_FAIL(static_cast(insert_op_) ->gen_calc_part_id_expr(dupkey_info.loc_table_id_, dupkey_info.index_tid_, calc_part_expr))) { LOG_WARN("fail to gen calc part id expr", K(dupkey_info), K(ret)); } if (OB_SUCC(ret)) { fetcher_op->set_table_id(dupkey_info.table_id_); fetcher_op->set_index_tid(dupkey_info.index_tid_); fetcher_op->set_only_data_table(dupkey_info.only_data_table_); dupkey_op = fetcher_op; } OZ(get_all_exprs().append(dupkey_info.conflict_exprs_)); OZ(get_all_exprs().append(dupkey_info.access_exprs_)); OZ(get_all_exprs().append(dupkey_info.output_exprs_)); OZ(get_all_exprs().append(calc_part_expr)); return ret; } int ObInsertLogPlan::generate_values_op_as_child(ObLogicalOperator*& top) { int ret = OB_SUCCESS; ObLogExprValues* values_op = NULL; ObInsertStmt* insert_stmt = static_cast(get_stmt()); const ObExecContext* exec_ctx = get_optimizer_context().get_exec_ctx(); if (OB_ISNULL(insert_stmt) || OB_ISNULL(exec_ctx)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(insert_stmt), K(exec_ctx), K(ret)); } else if (OB_ISNULL( values_op = static_cast(get_log_op_factory().allocate(*this, LOG_EXPR_VALUES)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("Allocate memory for ObLogInsertValues failed", K(ret)); } else { values_op->set_card(static_cast(insert_stmt->get_row_count())); values_op->set_cost( ObOptEstCost::get_cost_params().CPU_TUPLE_COST * static_cast(insert_stmt->get_row_count())); values_op->set_op_cost(values_op->get_cost()); values_op->set_need_columnlized(true); if (NULL != top) { values_op->add_child(top); } top = values_op; if (!insert_stmt->get_subquery_exprs().empty()) { if (OB_FAIL(allocate_subplan_filter_as_top(insert_stmt->get_value_vectors(), false, top))) { LOG_WARN("failed to allocate subplan filter as top", K(ret)); } else { /*do nothing*/ } } if (OB_FAIL(ret)) { /*do nothing*/ } else if (OB_FAIL(values_op->add_values_expr(insert_stmt->get_value_vectors()))) { LOG_WARN("failed to add values expr", K(ret)); } else if (NULL != exec_ctx && NULL != exec_ctx->get_my_session() && exec_ctx->get_my_session()->use_static_typing_engine() && OB_FAIL(values_op->add_str_values_array(insert_stmt->get_column_conv_functions()))) { LOG_WARN("fail to add_str_values_array", K(ret)); } else { /*do nothing*/ } } return ret; } bool ObInsertLogPlan::is_self_part_insert() { bool is_append = false; const ObInsertStmt* insert_stmt = static_cast(stmt_); if (insert_stmt != NULL && OB_PHY_PLAN_DISTRIBUTED == phy_plan_type_ && !insert_stmt->value_from_select() && !insert_stmt->has_global_index()) { is_append = true; } return is_append; } int ObInsertLogPlan::map_value_param_index() { int ret = OB_SUCCESS; ObInsertStmt* insert_stmt = NULL; int64_t param_cnt = 0; ObArray> params_row_map; if (OB_ISNULL(get_optimizer_context().get_exec_ctx())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get execute context failed", K(ret)); } else if (OB_ISNULL(get_optimizer_context().get_exec_ctx()->get_physical_plan_ctx())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get physical plan context failed", K(ret)); } else if (OB_ISNULL(insert_stmt = static_cast(get_stmt()))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("insert stmt is null"); } else { param_cnt = get_optimizer_context().get_exec_ctx()->get_physical_plan_ctx()->get_param_store().count() + insert_stmt->get_exec_param_ref_exprs().count(); ObSEArray row_indexs; if (OB_FAIL(params_row_map.prepare_allocate(param_cnt))) { LOG_WARN("reserve row params map failed", K(ret), K(param_cnt)); } else if (OB_FAIL(row_indexs.push_back(OB_INVALID_INDEX))) { LOG_WARN("store row index failed", K(ret)); } // init to OB_INVALID_INDEX for (int64_t i = 0; OB_SUCC(ret) && i < params_row_map.count(); ++i) { if (OB_FAIL(params_row_map.at(i).assign(row_indexs))) { LOG_WARN("init row params map failed", K(ret), K(i)); } } } if (OB_SUCC(ret)) { ObIArray& insert_values = insert_stmt->get_value_vectors(); int64_t insert_column_cnt = insert_stmt->get_values_desc().count(); ObSEArray param_idxs; for (int64_t i = 0; OB_SUCC(ret) && i < insert_values.count(); ++i) { param_idxs.reset(); if (OB_FAIL(ObRawExprUtils::extract_param_idxs(insert_values.at(i), param_idxs))) { LOG_WARN("extract param idxs failed", K(ret)); } for (int64_t j = 0; OB_SUCC(ret) && j < param_idxs.count(); ++j) { if (OB_UNLIKELY(param_idxs.at(j) < 0) || OB_UNLIKELY(param_idxs.at(j) >= param_cnt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("param idx is invalid", K(param_idxs.at(j)), K(param_cnt)); } else if (params_row_map.at(param_idxs.at(j)).count() == 1 && params_row_map.at(param_idxs.at(j)).at(0) == OB_INVALID_INDEX) { params_row_map.at(param_idxs.at(j)).at(0) = i / insert_column_cnt; } else if (OB_FAIL(add_var_to_array_no_dup(params_row_map.at(param_idxs.at(j)), i / insert_column_cnt))) { LOG_WARN("add index no duplicate failed", K(ret)); } } } } if (OB_SUCC(ret)) { if (OB_FAIL(row_params_map_.prepare_allocate(insert_stmt->get_row_count() + 1))) { LOG_WARN("prepare allocate row params map failed", K(ret), K(insert_stmt->get_row_count())); } for (int64_t i = 0; OB_SUCC(ret) && i < params_row_map.count(); ++i) { for (int64_t j = 0; OB_SUCC(ret) && j < params_row_map.at(i).count(); ++j) { if (params_row_map.at(i).at(j) == OB_INVALID_INDEX) { if (OB_FAIL(row_params_map_.at(0).push_back(i))) { LOG_WARN("add param index to row params map failed", K(ret), K(i), K(j)); } } else { if (OB_FAIL(row_params_map_.at(params_row_map.at(i).at(j) + 1).push_back(i))) { LOG_WARN("add param index to row params map failed", K(ret), K(i), K(j)); } } } } } return ret; }