提交 add9d0d1 编写于 作者: O obdev 提交者: wangzelin.wzl

Fix two bugs about join

上级 c55903a9
......@@ -11385,10 +11385,10 @@ int ObJoinOrder::extract_pushdown_quals(const ObIArray<ObRawExpr *> &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));
......
......@@ -5231,10 +5231,6 @@ int ObLogPlan::create_plan_tree_from_path(Path *path,
JoinPath *join_path = static_cast<JoinPath *>(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<ObLogJoin*>(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<SubQueryPath *>(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<uint64_t, 1> 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<uint64_t, 1> 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<uint64_t> &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<const AccessPath*>(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<const JoinPath *>(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);
......
......@@ -1287,10 +1287,6 @@ public:
common::ObIArray<int64_t> &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<uint64_t> &sfu_table_list);
int merge_same_sfu_table_list(uint64_t target_id,
int64_t begin_idx,
ObIArray<uint64_t> &src_table_list,
......
......@@ -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<ObRawExpr*> &get_join_conditions() { return join_conditions_; }
const common::ObIArray<ObRawExpr*> &get_join_conditions() const { return join_conditions_; }
TO_STRING_KV(N_TID, table_id_,
......
......@@ -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))) {
......
......@@ -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));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册