diff --git a/src/sql/optimizer/ob_join_order.cpp b/src/sql/optimizer/ob_join_order.cpp index f1a4d810c2..fe98c5346c 100644 --- a/src/sql/optimizer/ob_join_order.cpp +++ b/src/sql/optimizer/ob_join_order.cpp @@ -11385,10 +11385,10 @@ int ObJoinOrder::extract_pushdown_quals(const ObIArray &quals, ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexplected null", K(qual), K(ret)); // can not push down expr with subquery - } else if (qual->has_flag(CNT_ONETIME) || - qual->has_flag(CNT_PSEUDO_COLUMN) || - qual->has_flag(CNT_PRIOR) || - qual->has_flag(CNT_ROWNUM)) { + } else if (qual->has_flag(CNT_SUB_QUERY) && + (qual->has_flag(CNT_PSEUDO_COLUMN) || + qual->has_flag(CNT_PRIOR) || + qual->has_flag(CNT_ROWNUM))) { if (force_inner_nl) { ret = OB_ERR_UNEXPECTED; LOG_WARN("can not push down special qual", KPC(qual), K(ret)); diff --git a/src/sql/optimizer/ob_log_plan.cpp b/src/sql/optimizer/ob_log_plan.cpp index 783d29967d..974ab6b19f 100644 --- a/src/sql/optimizer/ob_log_plan.cpp +++ b/src/sql/optimizer/ob_log_plan.cpp @@ -5231,10 +5231,6 @@ int ObLogPlan::create_plan_tree_from_path(Path *path, JoinPath *join_path = static_cast(path); if (OB_FAIL(allocate_join_path(join_path, op))) { LOG_WARN("failed to allocate join path", K(ret)); - } else if (lib::is_mysql_mode() && - OB_FAIL(allocate_for_update_for_semi_anti_join(join_path, - static_cast(op)))) { - LOG_WARN("failed to allocate allocate for update for semi anti join", K(ret)); } else {/* do nothing */ } } else if (path->is_subquery_path()) { SubQueryPath *subquery_path = static_cast(path); @@ -11757,78 +11753,6 @@ int ObLogPlan::generate_column_expr(ObRawExprFactory &expr_factory, return ret; } -int ObLogPlan::allocate_for_update_for_semi_anti_join(JoinPath *join_path, - ObLogJoin *join_op) -{ - int ret = OB_SUCCESS; - if (OB_ISNULL(join_path) || OB_ISNULL(join_op)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret), K(join_path), K(join_op)); - } else if (IS_SEMI_ANTI_JOIN(join_path->join_type_)) { - const Path *left_path = join_path->left_path_; - const Path *right_path = join_path->right_path_; - ObLogicalOperator *left_child = join_op->get_left_table(); - ObLogicalOperator *right_child = join_op->get_right_table(); - if (OB_ISNULL(left_path) || OB_ISNULL(right_path)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret), K(left_path), K(right_path)); - } else if (IS_LEFT_SEMI_ANTI_JOIN(join_path->join_type_)) { - //for update need allocate before rigth table which in left semi/anti join becauese - //it isn't pk preserving. - ObSEArray sfu_table_list; - if (OB_FAIL(recursive_collect_sfu_table_ids(right_path, sfu_table_list))) { - LOG_WARN("failed to recursive collect sfu table ids", K(ret)); - } else if (sfu_table_list.empty()) { - //do nothing - } else if (OB_FAIL(allocate_for_update_as_top(right_child, sfu_table_list))) { - LOG_WARN("failed to allocate for update as top", K(ret)); - } else { - join_op->set_right_child(right_child); - } - } else if (IS_RIGHT_SEMI_ANTI_JOIN(join_path->join_type_)) { - //for update need allocate before left table which in right semi/anti join becauese - //it isn't pk preserving. - ObSEArray sfu_table_list; - if (OB_FAIL(recursive_collect_sfu_table_ids(left_path, sfu_table_list))) { - LOG_WARN("failed to recursive collect sfu table ids", K(ret)); - } else if (sfu_table_list.empty()) { - //do nothing - } else if (OB_FAIL(allocate_for_update_as_top(left_child, sfu_table_list))) { - LOG_WARN("failed to allocate for update as top", K(ret)); - } else { - join_op->set_left_child(left_child); - } - } else {/*do nothing*/} - } - return ret; -} - -int ObLogPlan::recursive_collect_sfu_table_ids(const Path *path, ObIArray &sfu_table_list) -{ - int ret = OB_SUCCESS; - if (OB_ISNULL(path)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpecpted null", K(ret), K(path)); - } else if (path->is_access_path()) { - const AccessPath* access_path = static_cast(path); - if (access_path->for_update_ && !table_is_allocated_for_update(access_path->table_id_)) { - if (OB_FAIL(sfu_table_list.push_back(access_path->table_id_))) { - LOG_WARN("failed to push back", K(ret)); - } else {/*do nothing*/} - } - } else if (path->is_join_path()) { - const JoinPath *join_path = static_cast(path); - if (OB_FAIL(SMART_CALL(recursive_collect_sfu_table_ids(join_path->left_path_, - sfu_table_list)))) { - LOG_WARN("failed to recursive collect sfu table ids", K(ret)); - } else if (OB_FAIL(SMART_CALL(recursive_collect_sfu_table_ids(join_path->right_path_, - sfu_table_list)))) { - LOG_WARN("failed to recursive collect sfu table ids", K(ret)); - } else {/*do nothing*/} - } else {/*do nothing*/} - return ret; -} - //mysql mode need distinguish different of for update, eg: /* * create table t1(c1 int primary key, c2 int); diff --git a/src/sql/optimizer/ob_log_plan.h b/src/sql/optimizer/ob_log_plan.h index 3c4256650a..30a6622bf3 100644 --- a/src/sql/optimizer/ob_log_plan.h +++ b/src/sql/optimizer/ob_log_plan.h @@ -1287,10 +1287,6 @@ public: common::ObIArray &get_alloc_sfu_list() { return alloc_sfu_list_; } - int allocate_for_update_for_semi_anti_join(JoinPath *join_path, ObLogJoin *join_op); - - int recursive_collect_sfu_table_ids(const Path *path, ObIArray &sfu_table_list); - int merge_same_sfu_table_list(uint64_t target_id, int64_t begin_idx, ObIArray &src_table_list, diff --git a/src/sql/resolver/dml/ob_dml_stmt.h b/src/sql/resolver/dml/ob_dml_stmt.h index 1bdec71f50..f2fce985db 100644 --- a/src/sql/resolver/dml/ob_dml_stmt.h +++ b/src/sql/resolver/dml/ob_dml_stmt.h @@ -266,6 +266,7 @@ struct TableItem return (is_generated_table() || is_temp_table()) && view_base_item_ != NULL ? view_base_item_->get_base_table_item() : *this; } + virtual bool has_for_update() const { return for_update_; } // if real table id, it is valid for all threads, // else if generated id, it is unique just during the thread session uint64_t table_id_; @@ -443,6 +444,11 @@ struct JoinedTable : public TableItem bool is_left_join() const { return LEFT_OUTER_JOIN == joined_type_; } bool is_right_join() const { return RIGHT_OUTER_JOIN == joined_type_; } bool is_full_join() const { return FULL_OUTER_JOIN == joined_type_; } + virtual bool has_for_update() const + { + return (left_table_ != NULL && left_table_->has_for_update()) + || (right_table_ != NULL && right_table_->has_for_update()); + } common::ObIArray &get_join_conditions() { return join_conditions_; } const common::ObIArray &get_join_conditions() const { return join_conditions_; } TO_STRING_KV(N_TID, table_id_, diff --git a/src/sql/rewrite/ob_transform_left_join_to_anti.cpp b/src/sql/rewrite/ob_transform_left_join_to_anti.cpp index b317a97d58..1b62f3dfdc 100644 --- a/src/sql/rewrite/ob_transform_left_join_to_anti.cpp +++ b/src/sql/rewrite/ob_transform_left_join_to_anti.cpp @@ -180,7 +180,8 @@ int ObTransformLeftJoinToAnti::transform_left_join_to_anti_join(ObDMLStmt *&stmt } else if (OB_FAIL(ObOptimizerUtil::remove_item(stmt->get_condition_exprs(), target_exprs))) { LOG_WARN("failed to remove condition exprs", K(ret)); } else if (is_root_table) { - if (right_table->is_joined_table() && + if ((right_table->is_joined_table() || + (lib::is_mysql_mode() && right_table->has_for_update())) && OB_FAIL(ObTransformUtils::create_view_with_table(stmt, ctx_, right_table, @@ -194,7 +195,14 @@ int ObTransformLeftJoinToAnti::transform_left_join_to_anti_join(ObDMLStmt *&stmt } else { TableItem *table = joined_table; ObDMLStmt *ref_query = NULL; - if (OB_FAIL(ObTransformUtils::create_view_with_table(stmt, + TableItem *view_table_for_update = NULL; + if (lib::is_mysql_mode() && right_table->has_for_update() && + OB_FAIL(ObTransformUtils::create_view_with_table(stmt, + ctx_, + right_table, + view_table_for_update))) { + LOG_WARN("failed to create semi view", K(ret)); + } else if (OB_FAIL(ObTransformUtils::create_view_with_table(stmt, ctx_, table, view_table))) { diff --git a/src/sql/rewrite/ob_transform_view_merge.cpp b/src/sql/rewrite/ob_transform_view_merge.cpp index 1c1850e23a..295bb18b22 100644 --- a/src/sql/rewrite/ob_transform_view_merge.cpp +++ b/src/sql/rewrite/ob_transform_view_merge.cpp @@ -356,7 +356,8 @@ int ObTransformViewMerge::check_semi_right_table_can_be_merged(ObDMLStmt *stmt, || ref_query->is_contains_assignment() || ref_query->has_sequence() || ref_query->is_hierarchical_query() - || ref_query->has_ora_rowscn()) { + || ref_query->has_ora_rowscn() + || (lib::is_mysql_mode() && ref_query->has_for_update())) { can_be = false; } else if (OB_FAIL(ref_query->has_rownum(has_rownum))) { LOG_WARN("failed to check has rownum expr", K(ret));