[FEAT MERGE]4_2_sql_feature

Co-authored-by: yinyj17 <yinyijun92@gmail.com>
Co-authored-by: xianyu-w <707512433@qq.com>
Co-authored-by: jingtaoye35 <1255153887@qq.com>
This commit is contained in:
zzg19950727
2023-04-28 11:12:11 +00:00
committed by ob-robot
parent 3bf92459f1
commit 3cada22bdc
161 changed files with 16883 additions and 4730 deletions

View File

@ -86,8 +86,21 @@ int ObTransformSimplifySubquery::transform_one_stmt(common::ObIArray<ObParentDML
LOG_TRACE("succeed to transform_exists_query", K(is_happened));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(transform_any_all_as_exists(stmt, is_happened))) {
LOG_WARN("failed to transform_any_all_as_exists", K(ret));
} else {
trans_happened |= is_happened;
OPT_TRACE("transform any/all as exists/not exists:", is_happened);
LOG_TRACE("succeed to transform_any_all_as_exists", K(is_happened));
}
}
if (OB_SUCC(ret) && trans_happened) {
if (OB_FAIL(add_transform_hint(*stmt))) {
if (OB_FAIL(stmt->adjust_subquery_list())) {
LOG_WARN("failed to adjust subquery list", K(ret));
} else if (OB_FAIL(stmt->formalize_query_ref_exprs())) {
LOG_WARN("failed to formalize query ref exprs");
} else if (OB_FAIL(add_transform_hint(*stmt))) {
LOG_WARN("failed to add transform hint", K(ret));
}
}
@ -265,71 +278,82 @@ int ObTransformSimplifySubquery::transform_not_expr(ObDMLStmt *stmt,
bool &trans_happened)
{
int ret = OB_SUCCESS;
bool is_happened = false;
trans_happened = false;
ObRawExprFactory *expr_factory = NULL;
if (OB_ISNULL(stmt) || OB_ISNULL(ctx_)) {
ObSEArray<ObRawExprPointer, 16> relation_expr_pointers;
if (OB_ISNULL(stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(ctx_));
} else if (OB_ISNULL(expr_factory = ctx_->expr_factory_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null ctx_ info", K(expr_factory));
} else {
ObSEArray<ObRawExpr *, 8> old_exprs;
ObSEArray<ObRawExpr *, 8> new_exprs;
for (int64_t i = 0; OB_SUCC(ret) && i < stmt->get_condition_size(); ++i) {
ObRawExpr *expr = stmt->get_condition_expr(i);
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (expr->get_expr_type() == T_OP_NOT &&
expr->has_flag(CNT_SUB_QUERY)) {
ObRawExpr *param = expr->get_param_expr(0);
ObItemType expr_type = param->get_expr_type();
if (OB_ISNULL(param)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(*param));
} else if (expr_type == T_OP_SQ_NSEQ) {
// same to T_OP_SQ_EQ as long as the expr is not null
// do nothing current now
} else if (param->has_flag(IS_WITH_ALL) || param->has_flag(IS_WITH_ANY)) {
ObRawExpr *new_param = NULL;
ObOpRawExpr *new_op_expr = NULL;
ObSubQueryKey key_flag = param->has_flag(IS_WITH_ALL) ?
T_WITH_ANY : T_WITH_ALL;
ObItemType new_type = get_opposite_expr_type(expr_type);
// 1. not col = all subquery can not be transformed
// 2. not col != any subquery can not be transformed
// 3. item type with T_INVALID can not be transformed
bool is_not_valid = (expr_type == T_OP_SQ_EQ &&
param->has_flag(IS_WITH_ALL)) ||
(expr_type == T_OP_SQ_NE &&
param->has_flag(IS_WITH_ANY)) ||
(new_type == T_INVALID);
if (is_not_valid) {
} else if (OB_FAIL(expr_factory->create_raw_expr(
ObRawExpr::EXPR_OPERATOR,
new_type,
new_param))) {
LOG_WARN("failed to create raw expr", K(ret));
} else if (OB_FALSE_IT(new_op_expr = static_cast<ObOpRawExpr *>(new_param))) {
} else if (OB_FALSE_IT(new_op_expr->set_subquery_key(key_flag))) {
} else if (OB_FAIL(append(new_op_expr->get_param_exprs(),
static_cast<ObOpRawExpr *>(param)->get_param_exprs()))) {
LOG_WARN("failed to append param exprs", K(ret));
} else if (OB_FALSE_IT(new_param = new_op_expr)) {
} else if (OB_FAIL(new_exprs.push_back(new_param))) {
LOG_WARN("failed to push back new expr", K(ret));
} else if (OB_FAIL(old_exprs.push_back(expr))) {
LOG_WARN("failed to push back old expr", K(ret));
}
}
}
}
if (OB_FAIL(ret) || old_exprs.empty() || new_exprs.empty()) {
} else if (OB_FAIL(stmt->replace_relation_exprs(old_exprs, new_exprs))) {
LOG_WARN("failed to replace expr in stmt", K(ret));
LOG_WARN("stmt is null", K(ret), K(stmt));
} else if (OB_FAIL(stmt->get_relation_exprs(relation_expr_pointers))) {
LOG_WARN("failed to get_relation_exprs", K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < relation_expr_pointers.count(); ++i) {
ObRawExpr *expr = NULL;
if (OB_FAIL(relation_expr_pointers.at(i).get(expr))) {
LOG_WARN("failed to get relation expr", K(ret));
} else if (OB_FAIL(do_transform_not_expr(expr, is_happened))) {
LOG_WARN("failed to transform expr", K(ret));
} else if (!is_happened) {
// do nothing
} else if (OB_FAIL(relation_expr_pointers.at(i).set(expr))) {
LOG_WARN("failed to set expr", K(ret));
} else {
trans_happened |= is_happened;
}
}
return ret;
}
int ObTransformSimplifySubquery::do_transform_not_expr(ObRawExpr *&expr, bool &trans_happened)
{
int ret = OB_SUCCESS;
ObRawExpr *param = NULL;
ObItemType expr_type = T_INVALID;
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), K(*param));
} else if (expr->get_expr_type() != T_OP_NOT ||
!expr->has_flag(CNT_SUB_QUERY)) {
// do nothing
} else if (OB_ISNULL(param = expr->get_param_expr(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(*param));
} else if (OB_FALSE_IT(expr_type = param->get_expr_type())) {
} else if (expr_type == T_OP_SQ_NSEQ) {
// same to T_OP_SQ_EQ as long as the expr is not null
// do nothing current now
} else if (param->has_flag(IS_WITH_ALL) || param->has_flag(IS_WITH_ANY)) {
ObRawExpr *new_param = NULL;
ObOpRawExpr *new_op_expr = NULL;
ObSubQueryKey key_flag = param->has_flag(IS_WITH_ALL) ?
T_WITH_ANY : T_WITH_ALL;
ObItemType new_type = get_opposite_expr_type(expr_type);
// 1. not col = all subquery can not be transformed
// 2. not col != any subquery can not be transformed
// 3. item type with T_INVALID can not be transformed
bool is_not_valid = (expr_type == T_OP_SQ_EQ &&
param->has_flag(IS_WITH_ALL)) ||
(expr_type == T_OP_SQ_NE &&
param->has_flag(IS_WITH_ANY)) ||
(new_type == T_INVALID);
if (is_not_valid) {
} else if (OB_FAIL(ctx_->expr_factory_->create_raw_expr(
ObRawExpr::EXPR_OPERATOR,
new_type,
new_param))) {
LOG_WARN("failed to create raw expr", K(ret));
} else if (OB_FALSE_IT(new_op_expr = static_cast<ObOpRawExpr *>(new_param))) {
} else if (OB_FALSE_IT(new_op_expr->set_subquery_key(key_flag))) {
} else if (OB_FAIL(append(new_op_expr->get_param_exprs(),
static_cast<ObOpRawExpr *>(param)->get_param_exprs()))) {
LOG_WARN("failed to append param exprs", K(ret));
} else if (OB_FAIL(new_op_expr->formalize(ctx_->session_info_))) {
LOG_WARN("failed to formalize expr", K(ret));
} else {
expr = new_op_expr;
trans_happened = true;
}
}
@ -773,7 +797,15 @@ int ObTransformSimplifySubquery::do_transform_any_all(ObDMLStmt *stmt, ObRawExpr
ret = OB_ERR_UNEXPECTED;
LOG_WARN("params have null", K(ret), K(stmt), K(expr));
} else if (IS_SUBQUERY_COMPARISON_OP(expr->get_expr_type())) {
if (OB_FAIL(transform_any_all_as_min_max(stmt, expr, is_happened))) {
if (OB_FAIL(eliminate_groupby_distinct_in_any_all(expr, is_happened))) {
LOG_WARN("failed to eliminate groupby distinct in any all", K(ret));
} else {
trans_happened |= is_happened;
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(transform_any_all_as_min_max(stmt, expr, is_happened))) {
LOG_WARN("failed to trans_any_all_as_min_max", K(ret));
} else {
trans_happened |= is_happened;
@ -785,6 +817,13 @@ int ObTransformSimplifySubquery::do_transform_any_all(ObDMLStmt *stmt, ObRawExpr
} else {
trans_happened |= is_happened;
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(add_limit_for_any_all_subquery(expr, is_happened))) {
LOG_WARN("failed to add limit for any all subquery", K(ret));
} else {
trans_happened |= is_happened;
}
}
return ret;
}
@ -1111,26 +1150,35 @@ ObItemType ObTransformSimplifySubquery::query_cmp_to_value_cmp(const ObItemType
int ObTransformSimplifySubquery::transform_exists_query(ObDMLStmt *stmt, bool &trans_happened)
{
int ret = OB_SUCCESS;
ObIArray<ObRawExpr*> &conditions = stmt->get_condition_exprs();
ObSEArray<ObRawExprPointer, 16> relation_expr_pointers;
if (OB_ISNULL(stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("stmt is null", K(ret), K(stmt));
ret = OB_INVALID_ARGUMENT;
LOG_WARN("stmt is NULL", K(ret));
} else if (!stmt->has_subquery()) {
//do nothing
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < conditions.count(); ++i) {
bool is_happened = false;
if (OB_FAIL(transform_one_expr(stmt, conditions.at(i), is_happened))) {
LOG_WARN("failed to transform one subquery expr", K(ret));
} else {
trans_happened |= is_happened;
}
}
// do nothing
} else if (OB_FAIL(stmt->get_relation_exprs(relation_expr_pointers))) {
LOG_WARN("failed to get_relation_exprs", K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < relation_expr_pointers.count(); ++i) {
ObRawExpr *target = NULL;
bool is_happened = false;
if (OB_FAIL(relation_expr_pointers.at(i).get(target))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("find to get expr from group", K(ret), K(target));
} else if (OB_FAIL(try_eliminate_subquery(stmt, target, is_happened))) {
LOG_WARN("fail to transform expr", K(ret));
} else if (!is_happened) {
// do nothing
} else if (OB_FAIL(relation_expr_pointers.at(i).set(target))) {
LOG_WARN("failed to set expr", K(ret));
} else {
trans_happened = true;
}
} // for end
return ret;
}
int ObTransformSimplifySubquery::transform_one_expr(ObDMLStmt *stmt, ObRawExpr *&expr, bool &trans_happened)
int ObTransformSimplifySubquery::try_eliminate_subquery(ObDMLStmt *stmt, ObRawExpr *&expr, bool &trans_happened)
{
int ret = OB_SUCCESS;
trans_happened = false;
@ -1237,32 +1285,6 @@ int ObTransformSimplifySubquery::eliminate_subquery(ObDMLStmt *stmt,
subq_expr->set_output_column(subquery->get_select_item_size());
}
}
} else if (expr->has_flag(IS_WITH_ANY) || expr->has_flag(IS_WITH_ALL)) {
if (OB_ISNULL(subq_expr = static_cast<ObQueryRefRawExpr *>(expr->get_param_expr(1)))
|| OB_ISNULL(left_hand = static_cast<ObRawExpr *>(expr->get_param_expr(0)))) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Subquery or left_hand expr is NULL", K(ret));
} else if (OB_ISNULL(subquery = subq_expr->get_ref_stmt())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Subquery stmt is NULL", K(ret));
} else if (OB_FAIL(eliminate_groupby_in_any_all(subquery, trans_happened))) {
LOG_WARN("Subquery elimination of group by in ANY, ALL fails", K(ret));
} else if (!subq_expr->get_exec_params().empty()) {
// correlated subquery
if (OB_FAIL(eliminate_distinct_in_any_all(subquery, trans_happened))) {
LOG_WARN("Subquery elimination of distinct in ANY, ALL fails", K(ret));
} else {/*do nothing*/}
} else if (!expr->has_flag(IS_WITH_ANY)) {
/*do nothing*/
} else if (OB_FAIL(check_need_add_limit(subquery, check_status))) {
LOG_WARN("check need add limit failed", K(ret));
} else if (!check_status) {
/*do nothing*/
} else if (OB_FAIL(ObTransformUtils::set_limit_expr(subquery, ctx_))) {
LOG_WARN("add limit expr failed", K(ret));
} else {
trans_happened = true;
}
}
}
return ret;
@ -1645,6 +1667,34 @@ int ObTransformSimplifySubquery::eliminate_groupby_in_any_all(ObSelectStmt *&sub
return ret;
}
int ObTransformSimplifySubquery::eliminate_groupby_distinct_in_any_all(ObRawExpr *expr, bool &trans_happened)
{
int ret = OB_SUCCESS;
ObQueryRefRawExpr *subq_expr = NULL;
ObSelectStmt *subquery = NULL;
if (OB_ISNULL(expr)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("get unexpected null", K(ret), K(expr));
} else if (!expr->has_flag(IS_WITH_ALL) && !expr->has_flag(IS_WITH_ANY)) {
} else if (OB_ISNULL(subq_expr = static_cast<ObQueryRefRawExpr *>(expr->get_param_expr(1))) ||
OB_ISNULL(static_cast<ObRawExpr *>(expr->get_param_expr(0)))) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Subquery or left_hand expr is NULL", K(ret));
} else if (OB_ISNULL(subquery = subq_expr->get_ref_stmt())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("subquery stmt is NULL", K(ret));
} else if (OB_FAIL(eliminate_groupby_in_any_all(subquery, trans_happened))) {
LOG_WARN("Subquery elimination of group by in ANY, ALL fails", K(ret));
} else if (!subq_expr->get_exec_params().empty()) {
// correlated subquery
if (OB_FAIL(eliminate_distinct_in_any_all(subquery, trans_happened))) {
LOG_WARN("Subquery elimination of distinct in ANY, ALL fails", K(ret));
} else {/*do nothing*/}
}
return ret;
}
int ObTransformSimplifySubquery::eliminate_distinct_in_any_all(ObSelectStmt *subquery,
bool &trans_happened)
{
@ -1666,6 +1716,38 @@ int ObTransformSimplifySubquery::eliminate_distinct_in_any_all(ObSelectStmt *sub
return ret;
}
int ObTransformSimplifySubquery::add_limit_for_any_all_subquery(ObRawExpr *expr, bool &trans_happened)
{
int ret = OB_SUCCESS;
ObQueryRefRawExpr *subq_expr = NULL;
ObSelectStmt *subquery = NULL;
bool check_status = false;
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (!expr->has_flag(IS_WITH_ANY)) {
/*do nothing*/
} else if (OB_ISNULL(subq_expr = static_cast<ObQueryRefRawExpr *>(expr->get_param_expr(1)))
|| OB_ISNULL(static_cast<ObRawExpr *>(expr->get_param_expr(0)))) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Subquery or left_hand expr is NULL", K(ret));
} else if (OB_ISNULL(subquery = subq_expr->get_ref_stmt())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("Subquery stmt is NULL", K(ret));
} else if (subq_expr->has_exec_param()) {
//do nothing
} else if (OB_FAIL(check_need_add_limit(subquery, check_status))) {
LOG_WARN("check need add limit failed", K(ret));
} else if (!check_status) {
/*do nothing*/
} else if (OB_FAIL(ObTransformUtils::set_limit_expr(subquery, ctx_))) {
LOG_WARN("add limit expr failed", K(ret));
} else {
trans_happened = true;
}
return ret;
}
int ObTransformSimplifySubquery::check_need_add_limit(ObSelectStmt *subquery, bool &need_add_limit)
{
int ret = OB_SUCCESS;
@ -1796,3 +1878,543 @@ int ObTransformSimplifySubquery::check_const_select(const ObSelectStmt &stmt,
}
return ret;
}
int ObTransformSimplifySubquery::try_trans_any_all_as_exists(ObDMLStmt *stmt,
ObRawExpr *&expr,
ObNotNullContext *not_null_ctx,
bool is_bool_expr,
bool &trans_happened)
{
int ret = OB_SUCCESS;
bool is_valid = false;
bool is_happened = false;
if (OB_ISNULL(stmt) || OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("params have null", K(ret), K(stmt), K(expr));
} else if (IS_SUBQUERY_COMPARISON_OP(expr->get_expr_type())) {
if (OB_FAIL(check_can_trans_as_exists(expr, is_bool_expr, is_valid))) {
LOG_WARN("failed to check in can tras as exists", K(ret));
} else if (!is_valid) {
// do nothing
} else if (OB_FAIL(do_trans_any_all_as_exists(expr,
not_null_ctx,
is_happened))) {
LOG_WARN("failed to do trans any all as exists", K(ret));
} else {
trans_happened |= is_happened;
}
} else if (!expr->has_flag(CNT_SUB_QUERY)) {
// do nothing
} else if (expr->get_expr_type() == T_OP_CASE) {
ObCaseOpRawExpr* case_expr = static_cast<ObCaseOpRawExpr*>(expr);
for (int64_t i = 0; OB_SUCC(ret) && i < case_expr->get_when_expr_size(); ++i) {
if (OB_FAIL(SMART_CALL(try_trans_any_all_as_exists(stmt,
case_expr->get_when_param_expr(i),
not_null_ctx,
true,
is_happened)))) {
LOG_WARN("failed to try_transform_any_all for param", K(ret));
} else {
trans_happened |= is_happened;
}
}
for (int64_t i = 0; OB_SUCC(ret) && i < case_expr->get_then_expr_size(); ++i) {
if (OB_FAIL(SMART_CALL(try_trans_any_all_as_exists(stmt,
case_expr->get_then_param_expr(i),
not_null_ctx,
false,
is_happened)))) {
LOG_WARN("failed to try_transform_any_all for param", K(ret));
} else {
trans_happened |= is_happened;
}
}
if (OB_FAIL(ret)) {
} else if (OB_NOT_NULL(case_expr->get_default_param_expr()) &&
OB_FAIL(SMART_CALL(try_trans_any_all_as_exists(
stmt,
case_expr->get_default_param_expr(),
not_null_ctx,
false,
is_happened)))) {
LOG_WARN("failed to try_transform_any_all for param", K(ret));
} else if (OB_FALSE_IT(trans_happened |= is_happened)) {
//do nothing
} else if (OB_NOT_NULL(case_expr->get_arg_param_expr()) &&
OB_FAIL(SMART_CALL(try_trans_any_all_as_exists(
stmt,
case_expr->get_arg_param_expr(),
not_null_ctx,
false,
is_happened)))) {
LOG_WARN("failed to try_transform_any_all for param", K(ret));
} else {
trans_happened |= is_happened;
}
} else {
//check children
bool child_is_bool_expr = expr->get_expr_type() == T_OP_OR ||
expr->get_expr_type() == T_OP_AND ||
expr->get_expr_type() == T_OP_XOR;
for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); ++i) {
if (OB_FAIL(SMART_CALL(try_trans_any_all_as_exists(stmt,
expr->get_param_expr(i),
not_null_ctx,
child_is_bool_expr,
is_happened)))) {
LOG_WARN("failed to try_transform_any_all for param", K(ret));
} else {
trans_happened |= is_happened;
}
}
}
return ret;
}
int ObTransformSimplifySubquery::do_trans_any_all_as_exists(ObRawExpr *&expr,
ObNotNullContext *not_null_ctx,
bool &trans_happened)
{
int ret = OB_SUCCESS;
ObRawExprFactory* expr_factory = NULL;
ObSelectStmt *right_stmt = NULL;
ObRawExpr *left_hand = NULL;
ObQueryRefRawExpr *right_hand = NULL;
ObSEArray<ObRawExpr*, 4> left_exprs;
ObOpRawExpr* exists_expr = NULL;
ObItemType cmp_type = T_INVALID;
ObSEArray<ObRawExpr*, 4> constraints;
ObSEArray<ObRawExpr*, 4> or_exprs;
trans_happened = false;
if (OB_ISNULL(ctx_) ||
OB_ISNULL(expr_factory = ctx_->expr_factory_) ||
OB_ISNULL(ctx_->session_info_) ||
OB_ISNULL(left_hand = expr->get_param_expr(0)) ||
OB_ISNULL(expr->get_param_expr(1)) ||
OB_UNLIKELY(!expr->get_param_expr(1)->is_query_ref_expr())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("NULL pointer Error", KP_(ctx), K(ret));
} else if (OB_FALSE_IT(right_hand =
static_cast<ObQueryRefRawExpr *>(expr->get_param_expr(1)))) {
} else if (OB_FAIL(prepare_trans_any_all_as_exists(right_hand, right_stmt))) {
LOG_WARN("failed to prepare trans any all as exists", K(ret));
} else if (T_OP_ROW != left_hand->get_expr_type() &&
OB_FAIL(left_exprs.push_back(left_hand))) {
LOG_WARN("failed to push back expr", K(ret));
} else if (T_OP_ROW == left_hand->get_expr_type() &&
OB_FAIL(append(left_exprs, static_cast<ObOpRawExpr *>(left_hand)->get_param_exprs()))) {
LOG_WARN("failed to append exprs", K(ret));
} else if (OB_ISNULL(right_stmt) ||
OB_UNLIKELY(left_exprs.count() != right_stmt->get_select_item_size())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("select item size not equal to in expr size", K(left_exprs.count()),
K(right_stmt->get_select_item_size()));
} else {
ObNotNullContext right_null_ctx(*ctx_, right_stmt);
if (expr->has_flag(IS_WITH_ALL) &&
OB_FAIL(right_null_ctx.generate_stmt_context(NULLABLE_SCOPE::NS_TOP))) {
LOG_WARN("failed to generate stmt context", K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < left_exprs.count(); ++i) {
ObOpRawExpr* cmp_expr = NULL;
ObRawExpr* left_expr = NULL;
ObRawExpr* exec_param = NULL;
ObRawExpr* op_expr = NULL;
if (OB_ISNULL(left_expr = left_exprs.at(i)) ||
OB_ISNULL(right_stmt->get_select_item(i).expr_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(left_expr));
} else if (OB_FAIL(ObRawExprUtils::get_exec_param_expr(*expr_factory,
right_hand,
left_expr,
exec_param))) {
LOG_WARN("failed to get exec param expr", K(ret));
} else if (OB_FAIL(query_cmp_to_exists_value_cmp(expr->get_expr_type(),
expr->has_flag(IS_WITH_ALL),
cmp_type))) {
LOG_WARN("failed to get query cmp to value cmp type", K(ret));
} else if (OB_FAIL(expr_factory->create_raw_expr(cmp_type, cmp_expr))) {
LOG_WARN("failed to create raw expr", K(ret));
} else if (OB_ISNULL(cmp_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(left_expr));
} else if (OB_FAIL(cmp_expr->set_param_exprs(exec_param,
right_stmt->get_select_item(i).expr_))) {
LOG_WARN("failed to set param exprs", K(ret));
} else if (OB_FAIL(cmp_expr->formalize(ctx_->session_info_))) {
LOG_WARN("failed to formalize cmp expr", K(ret));
} else if (OB_FAIL(cmp_expr->pull_relation_id())) {
LOG_WARN("failed to pull relation id", K(ret));
} else if (expr->has_flag(IS_WITH_ALL)) {
ObRawExpr* left_is_null_expr = NULL;
ObRawExpr* right_is_null_expr = NULL;
ObRawExpr* or_expr = NULL;
bool is_not_null = false;
constraints.reuse();
or_exprs.reuse();
if (OB_FAIL(or_exprs.push_back(cmp_expr))) {
LOG_WARN("failed to push back or expr");
} else if (not_null_ctx != NULL &&
OB_FAIL(ObTransformUtils::is_expr_not_null(*not_null_ctx,
left_expr,
is_not_null,
&constraints))) {
LOG_WARN("failed to check whether expr is nullable", K(ret));
} else if (is_not_null &&
OB_FAIL(ObTransformUtils::add_param_not_null_constraint(*ctx_, constraints))) {
LOG_WARN("failed to add param not null constraint", K(ret));
} else if (!is_not_null &&
OB_FAIL(ObRawExprUtils::build_is_not_null_expr(*expr_factory,
exec_param,
false,
left_is_null_expr))) {
LOG_WARN("failed to build is not null expr", K(ret));
} else if (!is_not_null &&
OB_FAIL(or_exprs.push_back(left_is_null_expr))) {
LOG_WARN("failed to push back expr", K(ret));
} else if (OB_FALSE_IT(is_not_null = false)) {
} else if (OB_FALSE_IT(constraints.reuse())) {
} else if (OB_FAIL(ObTransformUtils::is_expr_not_null(right_null_ctx,
right_stmt->get_select_item(i).expr_,
is_not_null,
&constraints))) {
LOG_WARN("failed to check whether expr is nullable", K(ret));
} else if (is_not_null &&
OB_FAIL(ObTransformUtils::add_param_not_null_constraint(*ctx_, constraints))) {
LOG_WARN("failed to add param not null constraint", K(ret));
} else if (!is_not_null &&
OB_FAIL(ObRawExprUtils::build_is_not_null_expr(*expr_factory,
right_stmt->get_select_item(i).expr_,
false,
right_is_null_expr))) {
LOG_WARN("failed to build is not null expr", K(ret));
} else if (!is_not_null &&
OB_FAIL(or_exprs.push_back(right_is_null_expr))) {
LOG_WARN("failed to push back expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_or_exprs(*expr_factory,
or_exprs,
or_expr))) {
LOG_WARN("failed to build or exprs", K(ret));
} else if (OB_ISNULL(or_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(or_expr));
} else if (OB_FAIL(or_expr->formalize(ctx_->session_info_))) {
LOG_WARN("failed to formalize expr", K(ret));
} else if (OB_FAIL(or_expr->pull_relation_id())) {
LOG_WARN("failed to pull releation id", K(ret));
} else {
op_expr = or_expr;
}
} else {
op_expr = cmp_expr;
}
if (OB_SUCC(ret) && OB_FAIL(right_stmt->get_condition_exprs().push_back(op_expr))) {
LOG_WARN("failed to push back op expr", K(ret));
}
}
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(expr_factory->create_raw_expr(expr->has_flag(IS_WITH_ALL)
? T_OP_NOT_EXISTS : T_OP_EXISTS,
exists_expr))) {
LOG_WARN("failed to create raw expr");
} else if (OB_FAIL(OB_ISNULL(exists_expr))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(exists_expr));
} else if (OB_FAIL(exists_expr->set_param_expr(right_hand))) {
LOG_WARN("failed to set param expr", K(ret));
} else if (OB_FAIL(exists_expr->formalize(ctx_->session_info_))) {
LOG_WARN("failed to formalize expr", K(ret));
} else {
expr = exists_expr;
trans_happened = true;
}
return ret;
}
int ObTransformSimplifySubquery::check_can_trans_as_exists(ObRawExpr* expr, bool is_bool_expr, bool& is_valid)
{
int ret = OB_SUCCESS;
ObQueryRefRawExpr* right_hand = NULL;
ObRawExpr* left_hand = NULL;
is_valid = false;
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("params have null", K(ret), K(expr));
} else if (!is_bool_expr ||
!IS_SUBQUERY_COMPARISON_OP(expr->get_expr_type()) ||
(!expr->has_flag(IS_WITH_ALL) &&
!expr->has_flag(IS_WITH_ANY))) {
// do nothing
} else if (OB_UNLIKELY(expr->get_param_count() != 2) ||
OB_ISNULL(left_hand = expr->get_param_expr(0)) ||
OB_ISNULL(expr->get_param_expr(1)) ||
OB_UNLIKELY(!expr->get_param_expr(1)->is_query_ref_expr())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("param expr is null", K(ret));
} else if (left_hand->has_flag(CNT_SUB_QUERY)) {
// do nothing
} else if (OB_FALSE_IT(right_hand = static_cast<ObQueryRefRawExpr*>(expr->get_param_expr(1)))) {
} else if (right_hand->get_ref_count() > 1) {
// do nothing
} else if (OB_FAIL(check_stmt_can_trans_as_exists(right_hand->get_ref_stmt(),
!right_hand->get_exec_params().empty(),
is_valid))) {
LOG_WARN("failed to check stmt can trans as exists", K(ret));
}
return ret;
}
int ObTransformSimplifySubquery::check_stmt_can_trans_as_exists(ObSelectStmt *stmt, bool is_correlated, bool &is_valid)
{
int ret = OB_SUCCESS;
bool contain_rownum = false;
is_valid = false;
if (OB_ISNULL(stmt) ||
OB_ISNULL(ctx_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("child stmt is null", K(ret));
} else if (OB_FAIL(stmt->has_rownum(contain_rownum))) {
LOG_WARN("failed to check child statement contain rownum", K(ret));
} else if (contain_rownum ||
stmt->has_limit()) {
// do nothing
} else if (stmt->is_set_stmt()) {
if (stmt->is_recursive_union()) {
} else if (stmt->get_set_op() == ObSelectStmt::EXCEPT) {
if (OB_UNLIKELY(stmt->get_set_query().empty())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get except set query is empty", K(ret));
} else if (OB_FAIL(SMART_CALL(check_stmt_can_trans_as_exists(stmt->get_set_query(0),
is_correlated,
is_valid)))) {
LOG_WARN("failted to check stmt can trans as exists", K(ret));
}
} else {
is_valid = true;
for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < stmt->get_set_query().count(); ++i) {
if (OB_FAIL(SMART_CALL(check_stmt_can_trans_as_exists(stmt->get_set_query(i),
is_correlated,
is_valid)))) {
LOG_WARN("failted to check stmt can trans as exists", K(ret));
}
}
}
} else if (stmt->is_contains_assignment() ||
stmt->is_hierarchical_query() ||
stmt->has_window_function() ||
stmt->has_rollup()) {
LOG_TRACE("stmt not support trans in as exists", K(stmt->is_contains_assignment()),
K(stmt->is_hierarchical_query()), K(stmt->has_window_function()),
K(stmt->has_rollup()));
} else if (is_correlated) {
is_valid = true;
} else if (stmt->has_group_by() ||
stmt->has_having()) {
// do nothing
} else {
ObArenaAllocator alloc;
EqualSets &equal_sets = ctx_->equal_sets_;
ObSEArray<ObRawExpr *, 4> const_exprs;
if (OB_FAIL(stmt->get_stmt_equal_sets(equal_sets, alloc, true))) {
LOG_WARN("failed to get stmt equal sets", K(ret));
} else if (OB_FAIL(ObOptimizerUtil::compute_const_exprs(stmt->get_condition_exprs(),
const_exprs))) {
LOG_WARN("failed to compute const equivalent exprs", K(ret));
} else {
ObRawExpr *sel_expr = NULL;
for (int64_t i = 0; OB_SUCC(ret) && !is_valid && i < stmt->get_select_item_size(); ++i) {
if (OB_ISNULL(sel_expr = stmt->get_select_item(i).expr_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("select expr is NULL", K(ret));
} else if (!sel_expr->is_column_ref_expr()) {
} else if (OB_FAIL(ObTransformUtils::is_match_index(ctx_->sql_schema_guard_,
stmt,
static_cast<ObColumnRefRawExpr *>(sel_expr),
is_valid,
&equal_sets,
&const_exprs))) {
LOG_WARN("failed to check is match index prefix", K(ret));
}
}
}
equal_sets.reuse();
}
return ret;
}
int ObTransformSimplifySubquery::query_cmp_to_exists_value_cmp(ObItemType type, bool is_with_all, ObItemType& new_type)
{
int64_t ret = OB_SUCCESS;
if (is_with_all) {
type = get_opposite_expr_type(type);
}
ret = ObTransformUtils::query_cmp_to_value_cmp(type, new_type);
return ret;
}
int ObTransformSimplifySubquery::prepare_trans_any_all_as_exists(ObQueryRefRawExpr* right_hand, ObSelectStmt *&trans_stmt)
{
int ret = OB_SUCCESS;
trans_stmt = NULL;
if (OB_ISNULL(right_hand) ||
OB_ISNULL(trans_stmt = right_hand->get_ref_stmt())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to prepare trans any all as exists", K(ret));
} else if (trans_stmt->is_spj()) {
} else if (OB_FAIL(ObTransformUtils::create_stmt_with_generated_table(ctx_,
trans_stmt,
trans_stmt))) {
LOG_WARN("failed to create stmt with generated table", K(ret));
} else {
right_hand->set_ref_stmt(trans_stmt);
}
return ret;
}
int ObTransformSimplifySubquery::transform_any_all_as_exists(ObDMLStmt *stmt, bool &trans_happened)
{
int ret = OB_SUCCESS;
bool is_happened = false;
if (OB_ISNULL(stmt) ||
OB_ISNULL(ctx_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else {
ObNotNullContext not_null_ctx(*ctx_, stmt);
for (int64_t i = 0; OB_SUCC(ret) && i < stmt->get_joined_tables().count(); ++i) {
if (OB_FAIL(transform_any_all_as_exists_joined_table(stmt,
stmt->get_joined_tables().at(i),
is_happened))) {
LOG_WARN("failed to flatten join condition exprs", K(ret));
} else {
trans_happened |= is_happened;
}
}
if (OB_FAIL(ret)) {
} else if (OB_FALSE_IT(not_null_ctx.reset())) {
} else if (OB_FAIL(not_null_ctx.generate_stmt_context(NULLABLE_SCOPE::NS_WHERE))) {
LOG_WARN("failed to generate where context", K(ret));
} else if (OB_FAIL(try_trans_any_all_as_exists(stmt,
stmt->get_condition_exprs(),
&not_null_ctx,
true,
is_happened))) {
LOG_WARN("failed to trans any all as exists", K(ret));
} else {
trans_happened |= is_happened;
}
if (OB_SUCC(ret) && stmt->is_select_stmt()) {
ObSelectStmt *select_stmt = static_cast<ObSelectStmt*>(stmt);
not_null_ctx.reset();
if (OB_FAIL(not_null_ctx.generate_stmt_context(NULLABLE_SCOPE::NS_TOP))) {
LOG_WARN("failed to generate where context", K(ret));
} else if (OB_FAIL(try_trans_any_all_as_exists(stmt,
select_stmt->get_having_exprs(),
&not_null_ctx,
true,
is_happened))) {
LOG_WARN("failed to try trans any all as exists", K(ret));
} else {
trans_happened |= is_happened;
}
for (int64_t i = 0; OB_SUCC(ret) && i < select_stmt->get_select_items().count(); ++i) {
if (OB_ISNULL(select_stmt->get_select_items().at(i).expr_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(try_trans_any_all_as_exists(stmt,
select_stmt->get_select_items().at(i).expr_,
&not_null_ctx,
false,
is_happened))) {
LOG_WARN("failed to try trans any all as exists", K(ret));
} else {
trans_happened |= is_happened;
}
}
}
}
return ret;
}
int ObTransformSimplifySubquery::transform_any_all_as_exists_joined_table(
ObDMLStmt* stmt,
TableItem *table,
bool &trans_happened)
{
int ret = OB_SUCCESS;
JoinedTable *join_table = NULL;
TableItem *left_table = NULL;
TableItem *right_table = NULL;
trans_happened = false;
bool cur_happened = false;
bool left_happened = false;
bool right_happened = false;
if (OB_ISNULL(table) ) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(table));
} else if (!table->is_joined_table()) {
/*do nothing*/
} else if (OB_ISNULL(join_table = static_cast<JoinedTable*>(table)) ||
OB_ISNULL(left_table = join_table->left_table_) ||
OB_ISNULL(right_table = join_table->right_table_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(join_table));
} else {
ObNotNullContext not_null_ctx(*ctx_, stmt);
if (left_table->is_joined_table() &&
OB_FAIL(not_null_ctx.add_joined_table(static_cast<JoinedTable *>(left_table)))) {
LOG_WARN("failed to add context", K(ret));
} else if (right_table->is_joined_table() &&
OB_FAIL(not_null_ctx.add_joined_table(static_cast<JoinedTable *>(right_table)))) {
LOG_WARN("failed to add context", K(ret));
} else if (OB_FAIL(not_null_ctx.add_filter(join_table->get_join_conditions()))) {
LOG_WARN("failed to add null reject conditions", K(ret));
} else if (OB_FAIL(try_trans_any_all_as_exists(stmt, join_table->get_join_conditions(),
&not_null_ctx, true, cur_happened))) {
LOG_WARN("failed to try trans any all as exists", K(ret));
} else if (OB_FAIL(SMART_CALL(transform_any_all_as_exists_joined_table(stmt,
join_table->left_table_,
left_happened)))) {
LOG_WARN("failed to flatten left child join condition exprs", K(ret));
} else if (OB_FAIL(SMART_CALL(transform_any_all_as_exists_joined_table(stmt,
join_table->right_table_,
right_happened)))) {
LOG_WARN("failed to flatten right child join condition exprs", K(ret));
} else {
trans_happened = cur_happened | left_happened | right_happened;
}
}
return ret;
}
int ObTransformSimplifySubquery::try_trans_any_all_as_exists(
ObDMLStmt *stmt,
ObIArray<ObRawExpr* > &exprs,
ObNotNullContext *not_null_cxt,
bool is_bool_expr,
bool &trans_happened)
{
int ret = OB_SUCCESS;
bool is_happened = false;
for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); ++i) {
if (OB_FAIL(try_trans_any_all_as_exists(stmt,
exprs.at(i),
not_null_cxt,
is_bool_expr,
is_happened))) {
LOG_WARN("failed to try trans any all as exists", K(ret));
} else {
trans_happened |= is_happened;
}
}
return ret;
}