add simplify subquery with dual exists rule
This commit is contained in:
@ -1270,6 +1270,13 @@ int ObTransformSimplifySubquery::eliminate_subquery(ObDMLStmt *stmt,
|
||||
}
|
||||
LOG_TRACE("finish to eliminate subquery", K(can_be_eliminated), K(ret));
|
||||
|
||||
} else if (OB_FAIL(empty_table_subquery_can_be_eliminated_in_exists(expr, can_be_eliminated))) {
|
||||
LOG_WARN("failed to check empty table subquery can be eliminate", K(ret));
|
||||
} else if (can_be_eliminated) {
|
||||
if (OB_FAIL(do_trans_empty_table_subquery_as_expr(expr, trans_happened))) {
|
||||
LOG_WARN("failed to do trans empty table subquery as expr", K(ret));
|
||||
}
|
||||
LOG_TRACE("finish to eliminate empty table subquery", K(ret));
|
||||
} else if (!can_be_eliminated) {
|
||||
if (OB_FAIL(simplify_select_items(stmt, expr->get_expr_type(), subquery, false, trans_happened))) {
|
||||
LOG_WARN("Simplify select items in EXISTS fails", K(ret));
|
||||
@ -2224,6 +2231,8 @@ int ObTransformSimplifySubquery::check_stmt_can_trans_as_exists(ObSelectStmt *st
|
||||
} else if (stmt->has_group_by() ||
|
||||
stmt->has_having()) {
|
||||
// do nothing
|
||||
} else if (0 == stmt->get_from_item_size()) {
|
||||
is_valid = true;
|
||||
} else {
|
||||
ObArenaAllocator alloc;
|
||||
EqualSets &equal_sets = ctx_->equal_sets_;
|
||||
@ -2425,4 +2434,111 @@ int ObTransformSimplifySubquery::try_trans_any_all_as_exists(
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
int ObTransformSimplifySubquery::empty_table_subquery_can_be_eliminated_in_exists(ObRawExpr *expr,
|
||||
bool &is_valid)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObQueryRefRawExpr* query_ref = NULL;
|
||||
ObSelectStmt* ref_stmt = NULL;
|
||||
bool contain_rownum = false;
|
||||
bool has_limit = false;
|
||||
is_valid = false;
|
||||
if (OB_ISNULL(expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (T_OP_EXISTS != expr->get_expr_type() &&
|
||||
T_OP_NOT_EXISTS != expr->get_expr_type()) {
|
||||
is_valid = false;
|
||||
} else if (OB_UNLIKELY(expr->get_param_count() != 1) ||
|
||||
OB_ISNULL(expr->get_param_expr(0)) ||
|
||||
OB_UNLIKELY(!expr->get_param_expr(0)->is_query_ref_expr())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected exists/not exists expr", K(ret));
|
||||
} else if (OB_FALSE_IT(query_ref = static_cast<ObQueryRefRawExpr*>(expr->get_param_expr(0)))) {
|
||||
} else if (OB_ISNULL(ref_stmt = query_ref->get_ref_stmt())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected ref stmt", K(ret));
|
||||
} else if (OB_FAIL(ref_stmt->has_rownum(contain_rownum))) {
|
||||
LOG_WARN("failed to check ref stmt has rownum", K(ret));
|
||||
} else if (OB_FAIL(check_limit(expr->get_expr_type(), ref_stmt, has_limit))) {
|
||||
LOG_WARN("failed to check limit", K(ret));
|
||||
} else if (contain_rownum || has_limit) {
|
||||
is_valid = false;
|
||||
} else if (query_ref->get_ref_count() > 1) {
|
||||
is_valid = false;
|
||||
} else if (0 != ref_stmt->get_from_item_size() ||
|
||||
0 == ref_stmt->get_condition_size() ||
|
||||
ref_stmt->is_set_stmt() ||
|
||||
ref_stmt->is_contains_assignment() ||
|
||||
ref_stmt->has_group_by() ||
|
||||
ref_stmt->has_having() ||
|
||||
ref_stmt->is_hierarchical_query() ||
|
||||
ref_stmt->has_sequence() ||
|
||||
ref_stmt->has_window_function()) {
|
||||
is_valid = false;
|
||||
} else {
|
||||
is_valid = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformSimplifySubquery::do_trans_empty_table_subquery_as_expr(ObRawExpr *&expr,
|
||||
bool &trans_happened)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObQueryRefRawExpr* query_ref = NULL;
|
||||
ObSelectStmt* ref_stmt = NULL;
|
||||
bool add_limit_constraint = false;
|
||||
ObSEArray<ObRawExpr*, 4> conditions;
|
||||
ObRawExpr *out_expr = NULL;
|
||||
trans_happened = false;
|
||||
if (OB_ISNULL(expr) ||
|
||||
OB_ISNULL(ctx_) ||
|
||||
OB_ISNULL(ctx_->expr_factory_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (OB_UNLIKELY(expr->get_param_count() != 1) ||
|
||||
OB_ISNULL(expr->get_param_expr(0)) ||
|
||||
OB_UNLIKELY(!expr->get_param_expr(0)->is_query_ref_expr())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected exists/not exists expr", K(ret));
|
||||
} else if (OB_FALSE_IT(query_ref = static_cast<ObQueryRefRawExpr*>(expr->get_param_expr(0)))) {
|
||||
} else if (OB_ISNULL(ref_stmt = query_ref->get_ref_stmt())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected ref stmt", K(ret));
|
||||
} else if (OB_FAIL(need_add_limit_constraint(expr->get_expr_type(), ref_stmt, add_limit_constraint))){
|
||||
LOG_WARN("failed to check limit constraints", K(ret));
|
||||
} else if (add_limit_constraint &&
|
||||
OB_FAIL(ObTransformUtils::add_const_param_constraints(ref_stmt->get_limit_expr(), ctx_))) {
|
||||
LOG_WARN("failed to add const param constraints", K(ret));
|
||||
} else if (OB_FAIL(conditions.assign(ref_stmt->get_condition_exprs()))) {
|
||||
LOG_WARN("failed to assign condition exprs", K(ret));
|
||||
} else if (ObTransformUtils::decorrelate(conditions, query_ref->get_exec_params())) {
|
||||
LOG_WARN("failed to decorrelate condition exprs", K(ret));
|
||||
} else if (OB_FAIL(ObRawExprUtils::build_and_expr(*ctx_->expr_factory_,
|
||||
conditions,
|
||||
out_expr))) {
|
||||
LOG_WARN("failed to formalize expr", K(ret));
|
||||
} else if (OB_ISNULL(out_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (T_OP_NOT_EXISTS == expr->get_expr_type() &&
|
||||
OB_FAIL(ObRawExprUtils::build_lnnvl_expr(*ctx_->expr_factory_,
|
||||
out_expr,
|
||||
out_expr))) {
|
||||
LOG_WARN("failed to build lnnvl expr", K(ret));
|
||||
} else if (OB_ISNULL(out_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (OB_FAIL(out_expr->formalize(ctx_->session_info_))) {
|
||||
LOG_WARN("failed to formalize expr", K(ret));
|
||||
} else if (OB_FAIL(out_expr->pull_relation_id())) {
|
||||
LOG_WARN("failed to pull relation id", K(ret));
|
||||
} else {
|
||||
expr = out_expr;
|
||||
trans_happened = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user