/** * 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_REWRITE #include "sql/resolver/dml/ob_select_stmt.h" #include "sql/rewrite/ob_transform_subquery_coalesce.h" #include "sql/rewrite/ob_stmt_comparer.h" #include "sql/rewrite/ob_transform_utils.h" #include "sql/optimizer/ob_optimizer_util.h" #include "sql/resolver/expr/ob_raw_expr_util.h" #include "sql/ob_sql_context.h" using namespace oceanbase::common; using namespace oceanbase::sql; int ObTransformSubqueryCoalesce::transform_one_stmt( common::ObIArray& parent_stmts, ObDMLStmt*& stmt, bool& trans_happened) { int ret = OB_SUCCESS; bool is_happened = false; trans_happened = false; if (OB_ISNULL(stmt)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("stmt is NULL", K(ret)); } else if (OB_FAIL(transform_same_exprs(stmt, stmt->get_condition_exprs(), trans_happened))) { LOG_WARN("failed to transform where conditions", K(ret)); } else if (!stmt->is_select_stmt()) { // do nothing } else if (OB_FAIL(transform_same_exprs(stmt, static_cast(stmt)->get_having_exprs(), is_happened))) { LOG_WARN("failed to transform same exprs", K(ret)); } else { trans_happened = trans_happened || is_happened; } if (OB_SUCC(ret)) { ObSEArray rule_based_equal_infos; ObSEArray cost_based_equal_infos; do { is_happened = false; ObDMLStmt* trans_stmt = NULL; rule_based_equal_infos.reset(); cost_based_equal_infos.reset(); bool rule_based_trans_happened = false; if (OB_FAIL(transform_diff_exprs( stmt, trans_stmt, rule_based_equal_infos, cost_based_equal_infos, rule_based_trans_happened))) { LOG_WARN("failed to transform exprs", K(ret)); } else if (OB_FAIL(append(stmt->get_query_ctx()->all_equal_param_constraints_, rule_based_equal_infos))) { LOG_WARN("failed to append equal infos", K(ret)); } else if (OB_ISNULL(trans_stmt)) { // do nothing } else if (OB_FAIL(accept_transform(parent_stmts, stmt, trans_stmt, is_happened))) { LOG_WARN("failed to accept transform", K(ret)); } else if (!is_happened) { // do nothing } else if (OB_FAIL(append(stmt->get_query_ctx()->all_equal_param_constraints_, cost_based_equal_infos))) { LOG_WARN("failed to append equal infos", K(ret)); } if (OB_SUCC(ret)) { trans_happened = trans_happened || rule_based_trans_happened || is_happened; } } while (OB_SUCC(ret) && is_happened); } return ret; } int ObTransformSubqueryCoalesce::transform_same_exprs(ObDMLStmt* stmt, ObIArray& conds, bool& is_happened) { int ret = OB_SUCCESS; ObSEArray copy_exprs; ObSEArray same_exprs; ObSEArray same_all_exprs; ObSEArray validity_exprs; ObSEArray remove_exprs; is_happened = false; if (OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("stmt is null", K(ret)); } else if (OB_FAIL(classify_conditions(conds, validity_exprs))) { LOG_WARN("failed to check conditions validity", K(ret)); } else { bool coalesce_happened = false; bool happened = false; bool all_happened = false; ObItemType item_type[8] = { T_OP_EXISTS, T_OP_NOT_EXISTS, T_OP_SQ_EQ, T_OP_SQ_NE, T_OP_SQ_GT, T_OP_SQ_GE, T_OP_SQ_LT, T_OP_SQ_LE}; for (int32_t i = 0; OB_SUCC(ret) && i < 8; ++i) { same_all_exprs.reset(); same_exprs.reset(); if (item_type[i] == T_OP_EXISTS || item_type[i] == T_OP_NOT_EXISTS) { if (OB_FAIL(get_same_classify_exprs(validity_exprs, same_exprs, item_type[i], CNT_SUB_QUERY))) { LOG_WARN("get the same classify exprs failed", K(ret)); } else if (OB_FAIL(copy_exprs.assign(same_exprs))) { LOG_WARN("failed to assign exprs", K(ret)); } else if (OB_FAIL(coalesce_same_exists_exprs(stmt, item_type[i], same_exprs, happened))) { LOG_WARN("failed to coalesce exists exprs", K(ret)); } else if (OB_FAIL(get_remove_exprs(copy_exprs, same_exprs, remove_exprs))) { LOG_WARN("failed to get remove exprs", K(ret)); } else { coalesce_happened |= happened; } } else if (OB_FAIL(get_same_classify_exprs(validity_exprs, same_exprs, item_type[i], IS_WITH_ANY))) { LOG_WARN("get the same classify exprs failed", K(ret)); } else if (OB_FAIL(copy_exprs.assign(same_exprs))) { LOG_WARN("failed to assign exprs", K(ret)); } else if (OB_FAIL(coalesce_same_any_all_exprs(stmt, T_ANY, same_exprs, happened))) { LOG_WARN("failed to coalesce any exprs", K(ret)); } else if (OB_FAIL(get_remove_exprs(copy_exprs, same_exprs, remove_exprs))) { LOG_WARN("failed to get remove exprs", K(ret)); } else if (OB_FAIL(get_same_classify_exprs(validity_exprs, same_all_exprs, item_type[i], IS_WITH_ALL))) { LOG_WARN("get the same classify exprs failed", K(ret)); } else if (OB_FAIL(copy_exprs.assign(same_all_exprs))) { LOG_WARN("failed to assign exprs", K(ret)); } else if (OB_FAIL(coalesce_same_any_all_exprs(stmt, T_ALL, same_all_exprs, all_happened))) { LOG_WARN("failed to coalesce all exprs", K(ret)); } else if (OB_FAIL(get_remove_exprs(copy_exprs, same_all_exprs, remove_exprs))) { LOG_WARN("failed to get remove exprs", K(ret)); } else { coalesce_happened = coalesce_happened | happened | all_happened; } } if (OB_SUCC(ret) && coalesce_happened) { if (OB_FAIL(ObOptimizerUtil::remove_item(conds, remove_exprs))) { LOG_WARN("failed to remove exprs", K(ret)); } } } return ret; } int ObTransformSubqueryCoalesce::get_same_classify_exprs(ObIArray& validity_exprs, ObIArray& same_classify_exprs, ObItemType ctype, ObExprInfoFlag flag) { int ret = OB_SUCCESS; ObRawExpr* expr = NULL; for (int32_t i = 0; OB_SUCC(ret) && i < validity_exprs.count(); ++i) { expr = validity_exprs.at(i); if (OB_ISNULL(expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("expr is null", K(ret)); } else if (expr->has_flag(flag) && expr->get_expr_type() == ctype && OB_FAIL(same_classify_exprs.push_back(expr))) { LOG_WARN("failed to push back same classify exprs", K(ret)); } else { /*do nothing*/ } } return ret; } int ObTransformSubqueryCoalesce::adjust_transform_types(uint64_t& transform_types) { int ret = OB_SUCCESS; if (cost_based_trans_tried_) { transform_types &= (~transformer_type_); } return ret; } int ObTransformSubqueryCoalesce::classify_conditions( ObIArray& conditions, ObIArray& validity_exprs) { int ret = OB_SUCCESS; ObOpRawExpr* op = NULL; for (int64_t i = 0; OB_SUCC(ret) && i < conditions.count(); ++i) { ObRawExpr* cond = NULL; bool is_valid = false; if (OB_ISNULL(cond = conditions.at(i))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("expr is null", K(ret), K(i)); } else if (cond->get_expr_type() != T_OP_EXISTS && cond->get_expr_type() != T_OP_NOT_EXISTS && !cond->has_flag(IS_WITH_ANY) && !cond->has_flag(IS_WITH_ALL)) { // do nothing } else if ((cond->get_expr_type() == T_OP_EXISTS || cond->get_expr_type() == T_OP_NOT_EXISTS) && OB_FAIL(check_query_ref_validity(cond->get_param_expr(0), is_valid))) { LOG_WARN("failed to check query ref validity", K(ret)); } else if (is_valid) { ret = validity_exprs.push_back(cond); } else if ((cond->has_flag(IS_WITH_ANY) || cond->has_flag(IS_WITH_ALL)) && OB_FAIL(check_query_ref_validity(cond->get_param_expr(1), is_valid))) { LOG_WARN("failed to check query ref validity", K(ret)); } else if (is_valid) { ret = validity_exprs.push_back(cond); } else { // do nothing } } return ret; } int ObTransformSubqueryCoalesce::get_remove_exprs( ObIArray& ori_exprs, ObIArray& remain_exprs, ObIArray& remove_exprs) { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < ori_exprs.count(); ++i) { if (ObOptimizerUtil::find_item(remain_exprs, ori_exprs.at(i))) { // do nothing } else if (OB_FAIL(remove_exprs.push_back(ori_exprs.at(i)))) { LOG_WARN("failed to push back first expr", K(ret)); } } return ret; } int ObTransformSubqueryCoalesce::check_query_ref_validity(ObRawExpr* expr, bool& is_valid) { int ret = OB_SUCCESS; ObQueryRefRawExpr* query_ref = NULL; is_valid = false; if (OB_ISNULL(expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("expr is null", K(ret), K(expr)); } else if (expr->is_query_ref_expr()) { ObSelectStmt* sub_stmt = NULL; query_ref = static_cast(expr); if (OB_ISNULL(sub_stmt = query_ref->get_ref_stmt())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("query ref is null", K(ret)); } else if (sub_stmt->is_spj() && sub_stmt->get_semi_infos().empty() && sub_stmt->get_subquery_exprs().empty()) { is_valid = true; } } return ret; } int ObTransformSubqueryCoalesce::coalesce_same_exists_exprs( ObDMLStmt* stmt, const ObItemType type, ObIArray& filters, bool& is_happened) { int ret = OB_SUCCESS; ObSEArray equal_infos; ObStmtMapInfo map_info; QueryRelation relation; ObQueryRefRawExpr* first_query_ref = NULL; ObQueryRefRawExpr* second_query_ref = NULL; ObSqlBitSet<> removed_items; int64_t remove_index = -1; is_happened = false; if (OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("params have null", K(ret)); } for (int64_t i = 0; OB_SUCC(ret) && i < filters.count(); ++i) { first_query_ref = get_exists_query_expr(filters.at(i)); for (int64_t j = i + 1; OB_SUCC(ret) && !removed_items.has_member(i) && j < filters.count(); ++j) { map_info.reset(); remove_index = -1; second_query_ref = get_exists_query_expr(filters.at(j)); if (removed_items.has_member(j)) { // do nothing } else if (OB_ISNULL(first_query_ref) || OB_ISNULL(second_query_ref)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("query ref is invalid", K(ret)); } else if (OB_FAIL(ObStmtComparer::check_stmt_containment( first_query_ref->get_ref_stmt(), second_query_ref->get_ref_stmt(), map_info, relation))) { LOG_WARN("failed to check stmt containment", K(ret)); } else if (relation == QueryRelation::LEFT_SUBSET || relation == QueryRelation::EQUAL) { remove_index = (type == T_OP_EXISTS ? j : i); } else if (relation == QueryRelation::RIGHT_SUBSET) { remove_index = (type == T_OP_EXISTS ? i : j); } if (OB_SUCC(ret) && remove_index != -1) { if (OB_FAIL(removed_items.add_member(remove_index))) { LOG_WARN("failed to add member", K(ret)); } else if (OB_FAIL(append(equal_infos, map_info.equal_param_map_))) { LOG_WARN("failed to append equal param map", K(ret)); } } } } if (OB_SUCC(ret) && (!removed_items.is_empty())) { ObSEArray new_filters; for (int64_t i = 0; OB_SUCC(ret) && i < filters.count(); ++i) { if (!removed_items.has_member(i)) { // the filter is not removed if (OB_FAIL(new_filters.push_back(filters.at(i)))) { LOG_WARN("failed to push back filter", K(ret)); } } else if (OB_FAIL( ObOptimizerUtil::remove_item(stmt->get_subquery_exprs(), get_exists_query_expr(filters.at(i))))) { LOG_WARN("failed to remove subquery expr", K(ret)); } } if (OB_SUCC(ret)) { if (OB_FAIL(filters.assign(new_filters))) { LOG_WARN("failed to assign new filters", K(ret)); } else if (OB_FAIL(append(stmt->get_query_ctx()->all_equal_param_constraints_, equal_infos))) { LOG_WARN("failed to append equal infos", K(ret)); } else { is_happened = true; } } } return ret; } int ObTransformSubqueryCoalesce::coalesce_same_any_all_exprs( ObDMLStmt* stmt, const ObItemType type, ObIArray& filters, bool& is_happened) { int ret = OB_SUCCESS; ObSEArray equal_infos; ObStmtMapInfo map_info; QueryRelation relation; ObQueryRefRawExpr* first_query_ref = NULL; ObRawExpr* first_left_expr = NULL; ObQueryRefRawExpr* second_query_ref = NULL; ObRawExpr* second_left_expr = NULL; ObSqlBitSet<> removed_items; int64_t remove_index = -1; is_happened = false; if (OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("params have null", K(ret)); } else { for (int64_t i = 0; OB_SUCC(ret) && i < filters.count(); ++i) { first_left_expr = get_any_all_left_hand_expr(filters.at(i)); first_query_ref = get_any_all_query_expr(filters.at(i)); for (int64_t j = i + 1; OB_SUCC(ret) && !removed_items.has_member(i) && j < filters.count(); ++j) { second_left_expr = get_any_all_left_hand_expr(filters.at(j)); second_query_ref = get_any_all_query_expr(filters.at(j)); map_info.reset(); remove_index = -1; if (removed_items.has_member(j)) { // do nothing } else if (OB_ISNULL(first_left_expr) || OB_ISNULL(first_query_ref) || OB_ISNULL(second_left_expr) || OB_ISNULL(second_query_ref)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("query ref is invalid", K(ret)); } else if (!first_left_expr->same_as(*second_left_expr)) { /*do nothing*/ } else if (OB_FAIL(ObStmtComparer::check_stmt_containment( first_query_ref->get_ref_stmt(), second_query_ref->get_ref_stmt(), map_info, relation))) { LOG_WARN("failed to check stmt containment", K(ret)); } else if (relation == QueryRelation::LEFT_SUBSET || relation == QueryRelation::EQUAL) { remove_index = (type == T_ANY ? j : i); } else if (relation == QueryRelation::RIGHT_SUBSET) { remove_index = (type == T_ANY ? i : j); } if (OB_SUCC(ret) && remove_index != -1) { if (OB_FAIL(removed_items.add_member(remove_index))) { LOG_WARN("failed to add member", K(ret)); } else if (OB_FAIL(append(equal_infos, map_info.equal_param_map_))) { LOG_WARN("failed to append equal param map", K(ret)); } } } } if (OB_SUCC(ret) && (!removed_items.is_empty())) { ObSEArray new_filters; ObOpRawExpr* temp_op = NULL; for (int64_t i = 0; OB_SUCC(ret) && i < filters.count(); ++i) { temp_op = static_cast(filters.at(i)); if (!removed_items.has_member(i)) { // the filter is not removed if (OB_FAIL(new_filters.push_back(filters.at(i)))) { LOG_WARN("failed to push back filter", K(ret)); } } else if (OB_FAIL(ObOptimizerUtil::remove_item( stmt->get_subquery_exprs(), static_cast(temp_op->get_param_expr(1))))) { LOG_WARN("failed to remove subquery expr", K(ret)); } } if (OB_SUCC(ret)) { if (OB_FAIL(filters.assign(new_filters))) { LOG_WARN("failed to assign new filters", K(ret)); } else if (OB_FAIL(append(stmt->get_query_ctx()->all_equal_param_constraints_, equal_infos))) { LOG_WARN("failed to append equal infos", K(ret)); } else { is_happened = true; } } } } return ret; } int ObTransformSubqueryCoalesce::transform_diff_exprs(ObDMLStmt* stmt, ObDMLStmt*& trans_stmt, ObIArray& rule_based_equal_infos, ObIArray& cost_based_equal_infos, bool& rule_based_trans_happened) { int ret = OB_SUCCESS; ObSEArray where_params; ObSEArray having_params; bool where_is_false = false; bool having_is_false = false; ObSelectStmt* select_stmt = NULL; ObSelectStmt* select_trans_stmt = NULL; rule_based_trans_happened = false; if (OB_ISNULL(stmt) || OB_ISNULL(ctx_) || OB_ISNULL(ctx_->stmt_factory_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("params have null", K(ret), K(stmt), K(ctx_)); } else if (stmt->is_select_stmt() && OB_ISNULL(select_stmt = static_cast(stmt))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("params have null", K(ret), K(stmt), K(select_stmt)); } else if (OB_FAIL(check_conditions_validity(stmt->get_condition_exprs(), where_params, where_is_false))) { LOG_WARN("failed to check condition validity", K(ret)); } else if (OB_NOT_NULL(select_stmt) && OB_FAIL(check_conditions_validity(select_stmt->get_having_exprs(), having_params, having_is_false))) { LOG_WARN("failed to check having validity", K(ret)); } else if (where_is_false && OB_FAIL(make_false(stmt->get_condition_exprs()))) { LOG_WARN("failed to make condition false", K(ret)); } else if (having_is_false && OB_FAIL(make_false(select_stmt->get_having_exprs()))) { LOG_WARN("failed to make condition false", K(ret)); } else if ((where_is_false || where_params.empty()) && (having_is_false || having_params.empty())) { // do nothing } else if (OB_FAIL(ObTransformUtils::copy_stmt(*ctx_->stmt_factory_, stmt, trans_stmt))) { LOG_WARN("failed to copy stmt", K(ret)); } else if (OB_FAIL(trans_stmt->adjust_statement_id())) { LOG_WARN("failed to adjust stmt id", K(ret)); } else if (trans_stmt->is_select_stmt() && OB_ISNULL(select_trans_stmt = static_cast(trans_stmt))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("params have null", K(ret), K(trans_stmt), K(select_trans_stmt)); } else if (!where_is_false && OB_FAIL(coalesce_diff_exists_exprs(trans_stmt, trans_stmt->get_condition_exprs(), where_params))) { LOG_WARN("failed to do coalesce diff where conditions", K(ret)); } else if (!where_is_false && OB_FAIL(coalesce_diff_any_all_exprs(trans_stmt, trans_stmt->get_condition_exprs(), where_params))) { LOG_WARN("failed to do coalesce diff where conditions", K(ret)); } else if (OB_NOT_NULL(select_trans_stmt) && !having_is_false && OB_FAIL(coalesce_diff_any_all_exprs(trans_stmt, select_trans_stmt->get_having_exprs(), having_params))) { LOG_WARN("failed to do coalesce diff having conditions", K(ret)); } if (OB_SUCC(ret)) { rule_based_trans_happened = where_is_false || having_is_false; ObIArray* where_equal_infos = where_is_false ? &rule_based_equal_infos : &cost_based_equal_infos; ObIArray* having_equal_infos = having_is_false ? &rule_based_equal_infos : &cost_based_equal_infos; for (int64_t i = 0; OB_SUCC(ret) && i < where_params.count(); ++i) { if (OB_FAIL(append(*where_equal_infos, where_params.at(i).map_info_.equal_param_map_))) { LOG_WARN("failed to append equal infos", K(ret)); } } for (int64_t i = 0; OB_SUCC(ret) && i < having_params.count(); ++i) { if (OB_FAIL(append(*having_equal_infos, having_params.at(i).map_info_.equal_param_map_))) { LOG_WARN("failed to append equal infos", K(ret)); } } } return ret; } int ObTransformSubqueryCoalesce::check_conditions_validity( ObIArray& conds, ObIArray& trans_params, bool& has_false_conds) { int ret = OB_SUCCESS; ObSEArray validity_exprs; TransformParam param; ObSqlBitSet<> removed; QueryRelation relation = QueryRelation::UNCOMPARABLE; has_false_conds = false; bool is_used = false; if (OB_FAIL(classify_conditions(conds, validity_exprs))) { LOG_WARN("failed to check conditions validity", K(ret)); } else { ObSEArray left_exprs; ObSEArray right_exprs; ObItemType left_type[7] = {T_OP_EXISTS, T_OP_SQ_EQ, T_OP_SQ_NE, T_OP_SQ_LT, T_OP_SQ_LE, T_OP_SQ_GT, T_OP_SQ_GE}; ObItemType right_type[7] = { T_OP_NOT_EXISTS, T_OP_SQ_NE, T_OP_SQ_EQ, T_OP_SQ_GE, T_OP_SQ_GT, T_OP_SQ_LE, T_OP_SQ_LT}; for (int64_t k = 0; OB_SUCC(ret) && !has_false_conds && k < 7; ++k) { left_exprs.reset(); right_exprs.reset(); if (T_OP_EXISTS == left_type[k]) { // exists if (OB_FAIL(get_same_classify_exprs(validity_exprs, left_exprs, left_type[k], CNT_SUB_QUERY))) { LOG_WARN("get the same classify exprs failed", K(ret)); } else if (OB_FAIL(get_same_classify_exprs(validity_exprs, right_exprs, right_type[k], CNT_SUB_QUERY))) { LOG_WARN("get the same classify exprs failed", K(ret)); } else { for (int64_t i = 0; OB_SUCC(ret) && !has_false_conds && i < left_exprs.count(); ++i) { ObQueryRefRawExpr* exists_query = get_exists_query_expr(left_exprs.at(i)); is_used = false; for (int64_t j = 0; OB_SUCC(ret) && !is_used && !has_false_conds && j < right_exprs.count(); ++j) { ObQueryRefRawExpr* not_exists_query = get_exists_query_expr(right_exprs.at(j)); if (!removed.has_member(j)) { param.exists_expr_ = left_exprs.at(i); param.not_exists_expr_ = right_exprs.at(j); param.trans_flag_ = EXISTS_NOT_EXISTS; param.map_info_.reset(); if (OB_ISNULL(exists_query) || OB_ISNULL(not_exists_query)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("query ref exprs are null", K(ret)); } else if (OB_FAIL(ObStmtComparer::check_stmt_containment(not_exists_query->get_ref_stmt(), exists_query->get_ref_stmt(), param.map_info_, relation))) { LOG_WARN("failed to check stmt containment", K(ret)); } else if (relation == QueryRelation::RIGHT_SUBSET || relation == QueryRelation::EQUAL) { has_false_conds = true; is_used = true; trans_params.reset(); if (OB_FAIL(trans_params.push_back(param))) { LOG_WARN("failed to push back transform param", K(ret)); } } else if (relation == QueryRelation::LEFT_SUBSET) { if (OB_FAIL(removed.add_member(j))) { LOG_WARN("failed to add member into bit set", K(ret)); } else if (OB_FAIL(trans_params.push_back(param))) { LOG_WARN("failed to push back transform param", K(ret)); } else { is_used = true; } } else { } } } } } } else if (!has_false_conds) { // any, all if (OB_FAIL(get_same_classify_exprs(validity_exprs, left_exprs, left_type[k], IS_WITH_ANY))) { LOG_WARN("get the same classify exprs failed", K(ret)); } else if (OB_FAIL(get_same_classify_exprs(validity_exprs, right_exprs, right_type[k], IS_WITH_ALL))) { LOG_WARN("get the same classify exprs failed", K(ret)); } else if ((T_OP_SQ_LT == left_type[k] || T_OP_SQ_GT == left_type[k]) && OB_FAIL(get_same_classify_exprs( validity_exprs, right_exprs, right_type[k + 1], IS_WITH_ALL))) { //>any vs & trans_params, bool& has_false_conds, bool& is_used, bool can_coalesce) { int ret = OB_SUCCESS; has_false_conds = false; is_used = false; QueryRelation relation = QueryRelation::UNCOMPARABLE; ObRawExpr* first_left_expr = get_any_all_left_hand_expr(param.any_expr_); ObQueryRefRawExpr* first_query_ref = get_any_all_query_expr(param.any_expr_); ObRawExpr* second_left_expr = get_any_all_left_hand_expr(param.all_expr_); ObQueryRefRawExpr* second_query_ref = get_any_all_query_expr(param.all_expr_); if (OB_ISNULL(first_left_expr) || OB_ISNULL(first_query_ref) || OB_ISNULL(second_left_expr) || OB_ISNULL(second_query_ref)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("query ref exprs are null", K(ret)); } else if (!first_left_expr->same_as(*second_left_expr)) { /*do nothing*/ } else if (OB_FAIL(ObStmtComparer::check_stmt_containment( second_query_ref->get_ref_stmt(), first_query_ref->get_ref_stmt(), param.map_info_, relation))) { LOG_WARN("failed to check stmt containment", K(ret)); } else if (relation == QueryRelation::RIGHT_SUBSET || relation == QueryRelation::EQUAL) { has_false_conds = true; trans_params.reset(); is_used = true; if (OB_FAIL(trans_params.push_back(param))) { LOG_WARN("failed to push back transform param", K(ret)); } } else if (can_coalesce && relation == QueryRelation::LEFT_SUBSET) { if (OB_FAIL(trans_params.push_back(param))) { LOG_WARN("failed to push back transform param", K(ret)); } else { is_used = true; } } return ret; } /** * @brief ObTransformSubqueryCoalesce::coalesce_diff_exists_exprs * 1. remove merged exprs from cond_exprs * 2. merge exists and not exists * 3. add a new expr into cond_exprs * @return */ int ObTransformSubqueryCoalesce::coalesce_diff_exists_exprs( ObDMLStmt* stmt, ObIArray& cond_exprs, ObIArray& trans_params) { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < trans_params.count(); ++i) { ObRawExpr* new_exists_expr = NULL; TransformParam& param = trans_params.at(i); if (param.trans_flag_ == EXISTS_NOT_EXISTS) { ObQueryRefRawExpr* exist_query = get_exists_query_expr(param.exists_expr_); ObQueryRefRawExpr* not_exist_query = get_exists_query_expr(param.not_exists_expr_); ObQueryRefRawExpr* new_exists_query = NULL; if (OB_ISNULL(exist_query) || OB_ISNULL(not_exist_query)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("params are invalid", K(ret), K(exist_query), K(not_exist_query)); } else if (OB_FAIL(merge_exists_subqueries(param, new_exists_expr))) { LOG_WARN("failed to merge subqueries", K(ret)); } else if (OB_FAIL(ObOptimizerUtil::remove_item(cond_exprs, param.exists_expr_))) { LOG_WARN("failed to remove item", K(ret)); } else if (OB_FAIL(ObOptimizerUtil::remove_item(cond_exprs, param.not_exists_expr_))) { LOG_WARN("failed to remove item", K(ret)); } else if (OB_FAIL(cond_exprs.push_back(new_exists_expr))) { LOG_WARN("failed to push back new exists expr", K(ret)); } else if (OB_FAIL(ObOptimizerUtil::remove_item(stmt->get_subquery_exprs(), exist_query))) { LOG_WARN("failed to remove subquery ref expr", K(ret)); } else if (OB_FAIL(ObOptimizerUtil::remove_item(stmt->get_subquery_exprs(), not_exist_query))) { LOG_WARN("failed to remove subquery ref expr", K(ret)); } else if (OB_ISNULL(new_exists_query = get_exists_query_expr(new_exists_expr))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("the new exists expr is invalid", K(ret)); } else if (OB_FAIL(stmt->get_subquery_exprs().push_back(new_exists_query))) { LOG_WARN("failed to push back new exist query", K(ret)); } else { /*do nothing*/ } } else { /*do nothing*/ } } return ret; } /** * @brief ObTransformSubqueryCoalesce::coalesce_diff_any_all_exprs * 1. remove merged exprs from cond_exprs * 2. merge any_subquery and all_subquery * 3. add a new expr into cond_exprs * @return */ int ObTransformSubqueryCoalesce::coalesce_diff_any_all_exprs( ObDMLStmt* stmt, ObIArray& cond_exprs, ObIArray& trans_params) { int ret = OB_SUCCESS; if (OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null ptr", K(stmt), K(ret)); } else { ObQueryRefRawExpr* any_ref_expr = NULL; ObQueryRefRawExpr* all_ref_expr = NULL; ObRawExpr* old_any_expr = NULL; ObRawExpr* old_all_expr = NULL; for (int64_t i = 0; OB_SUCC(ret) && i < trans_params.count(); ++i) { ObRawExpr* new_any_all_expr = NULL; TransformParam& param = trans_params.at(i); if (param.trans_flag_ == ANY_ALL) { any_ref_expr = get_any_all_query_expr(param.any_expr_); all_ref_expr = get_any_all_query_expr(param.all_expr_); old_any_expr = param.any_expr_; old_all_expr = param.all_expr_; ObQueryRefRawExpr* new_any_all_query = NULL; if (OB_ISNULL(any_ref_expr) || OB_ISNULL(all_ref_expr) || OB_ISNULL(old_any_expr) || OB_ISNULL(old_all_expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("params are invalid", K(ret), K(any_ref_expr), K(all_ref_expr), K(old_any_expr), K(old_all_expr)); } else if (OB_FAIL(merge_any_all_subqueries(any_ref_expr, all_ref_expr, param, new_any_all_expr))) { LOG_WARN("failed to merge subqueries", K(ret)); } else if (OB_FAIL(ObOptimizerUtil::remove_item(cond_exprs, old_any_expr))) { LOG_WARN("failed to remove item", K(ret)); } else if (OB_FAIL(ObOptimizerUtil::remove_item(cond_exprs, old_all_expr))) { LOG_WARN("failed to remove item", K(ret)); } else if (OB_FAIL(cond_exprs.push_back(new_any_all_expr))) { LOG_WARN("failed to push back new any all expr", K(ret)); } else if (OB_FAIL(ObOptimizerUtil::remove_item(stmt->get_subquery_exprs(), any_ref_expr))) { LOG_WARN("failed to remove subquery ref expr", K(ret)); } else if (OB_FAIL(ObOptimizerUtil::remove_item(stmt->get_subquery_exprs(), all_ref_expr))) { LOG_WARN("failed to remove subquery ref expr", K(ret)); } else if (OB_ISNULL(new_any_all_query = get_any_all_query_expr(new_any_all_expr))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("the new any all expr is invalid", K(ret)); } else if (OB_FAIL(stmt->get_subquery_exprs().push_back(new_any_all_query))) { LOG_WARN("failed to push back new any all query", K(ret)); } else if (OB_FAIL(stmt->pull_all_expr_relation_id_and_levels())) { LOG_WARN("failed to form pull up expr id and level", K(ret)); } else if (OB_FAIL(stmt->formalize_stmt(ctx_->session_info_))) { LOG_WARN("formalize stmt failed", K(ret)); } else { /*do nothing */ } } } } return ret; } int ObTransformSubqueryCoalesce::merge_exists_subqueries(TransformParam& trans_param, ObRawExpr*& new_exist_expr) { int ret = OB_SUCCESS; ObRawExprFactory* expr_factory = NULL; ObStmtFactory* stmt_factory = NULL; ObSEArray old_cols; ObSEArray new_cols; ObSEArray extra_conds; ObQueryRefRawExpr* exist_query_ref = NULL; ObQueryRefRawExpr* not_exist_query_ref = NULL; ObQueryRefRawExpr* new_query_ref = NULL; ObSelectStmt* exist_stmt = NULL; ObSelectStmt* not_exist_stmt = NULL; ObSelectStmt* new_exist_stmt = NULL; const ObStmtMapInfo& map_info = trans_param.map_info_; if (OB_ISNULL(ctx_) || OB_ISNULL(expr_factory = ctx_->expr_factory_) || OB_ISNULL(stmt_factory = ctx_->stmt_factory_) || OB_ISNULL(exist_query_ref = get_exists_query_expr(trans_param.exists_expr_)) || OB_ISNULL(not_exist_query_ref = get_exists_query_expr(trans_param.not_exists_expr_)) || OB_ISNULL(exist_stmt = exist_query_ref->get_ref_stmt()) || OB_ISNULL(not_exist_stmt = not_exist_query_ref->get_ref_stmt()) || OB_UNLIKELY(map_info.cond_map_.count() != not_exist_stmt->get_condition_size()) || OB_UNLIKELY(map_info.table_map_.count() != not_exist_stmt->get_table_size())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("exist exprs are not valid", K(ret), K(expr_factory), K(stmt_factory), K(exist_query_ref), K(not_exist_query_ref), K(exist_stmt), K(not_exist_stmt)); } else if (OB_FAIL(ObRawExprUtils::copy_expr( *expr_factory, trans_param.exists_expr_, new_exist_expr, COPY_REF_DEFAULT))) { LOG_WARN("failed to copy exist expr", K(ret)); } else if (OB_FAIL(expr_factory->create_raw_expr(T_INVALID, new_query_ref))) { LOG_WARN("failed to create query ref expr", K(ret)); } else if (OB_FAIL(new_query_ref->assign(*exist_query_ref))) { LOG_WARN("failed to assign query ref expr", K(ret)); } else if (OB_FAIL(ObTransformUtils::copy_stmt( *stmt_factory, exist_stmt, reinterpret_cast(new_exist_stmt)))) { LOG_WARN("failed to copy exist stmt", K(ret)); } else if (OB_FAIL(new_exist_stmt->adjust_statement_id())) { LOG_WARN("failed to adjust stmt id", K(ret)); } else { new_query_ref->set_ref_stmt(new_exist_stmt); new_exist_expr->get_param_expr(0) = new_query_ref; } for (int64_t i = 0; OB_SUCC(ret) && i < not_exist_stmt->get_condition_size(); ++i) { ObRawExpr* new_cond_expr = NULL; if (map_info.cond_map_.at(i) >= 0 && map_info.cond_map_.at(i) < new_exist_stmt->get_condition_size()) { // both stmt has the condition } else if (OB_FAIL(ObRawExprUtils::copy_expr( *expr_factory, not_exist_stmt->get_condition_expr(i), new_cond_expr, COPY_REF_DEFAULT))) { LOG_WARN("failed to copy condition", K(ret)); } else if (OB_FAIL(extra_conds.push_back(new_cond_expr))) { LOG_WARN("failed to push back condition", K(ret)); } } for (int64_t i = 0; OB_SUCC(ret) && i < not_exist_stmt->get_column_size(); ++i) { ColumnItem& col_item = not_exist_stmt->get_column_items().at(i); ObColumnRefRawExpr* col_expr = not_exist_stmt->get_column_items().at(i).expr_; ObRawExpr* new_expr = NULL; TableItem* new_table_item = NULL; int64_t idx = not_exist_stmt->get_table_bit_index(col_item.table_id_) - 1; if (idx < 0 || idx >= map_info.table_map_.count() || map_info.table_map_.at(idx) < 0 || map_info.table_map_.at(idx) >= new_exist_stmt->get_table_size() || OB_ISNULL(new_table_item = new_exist_stmt->get_table_item(map_info.table_map_.at(idx)))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table is not mapped", K(ret), K(idx)); } else if (OB_NOT_NULL( new_expr = new_exist_stmt->get_column_expr_by_id(new_table_item->table_id_, col_item.column_id_))) { // do nothing } else if (OB_FAIL(ObRawExprUtils::copy_expr(*expr_factory, col_item.expr_, new_expr, COPY_REF_SHARED))) { LOG_WARN("failed to copy expr", K(ret)); } else { ColumnItem new_col_item; new_col_item.table_id_ = new_table_item->table_id_; new_col_item.column_id_ = col_item.column_id_; new_col_item.column_name_ = col_item.column_name_; new_col_item.expr_ = static_cast(new_expr); new_col_item.expr_->set_table_id(new_table_item->table_id_); new_col_item.expr_->set_table_name(new_table_item->table_name_); if (OB_FAIL(new_exist_stmt->add_column_item(new_col_item))) { LOG_WARN("failed to add column item", K(ret)); } } if (OB_SUCC(ret)) { if (OB_FAIL(old_cols.push_back(col_expr))) { LOG_WARN("failed to append column expr", K(ret)); } else if (OB_FAIL(new_cols.push_back(new_expr))) { LOG_WARN("failed to append column expr", K(ret)); } } } if (OB_SUCC(ret)) { // create having exprs // having sum(case when conds then 1 else 0 end) = 0 ObCaseOpRawExpr* case_expr = NULL; ObConstRawExpr* one_expr = NULL; ObConstRawExpr* zero_expr = NULL; ObConstRawExpr* equal_value = NULL; ObAggFunRawExpr* sum_expr = NULL; ObRawExpr* equal_expr = NULL; ObRawExpr* when_expr = NULL; if (OB_FAIL(expr_factory->create_raw_expr(T_OP_CASE, case_expr))) { LOG_WARN("failed to create case expr", K(ret)); } else if (OB_FAIL(create_and_expr(extra_conds, when_expr))) { LOG_WARN("failed to create and expr", K(ret)); } else if (OB_FAIL(ObRawExprUtils::build_const_int_expr(*expr_factory, ObIntType, 1L, one_expr))) { LOG_WARN("failed to build const int expr", K(ret)); } else if (OB_FAIL(ObRawExprUtils::build_const_int_expr(*expr_factory, ObIntType, 0L, zero_expr))) { LOG_WARN("failed to build const int expr", K(ret)); } else if (OB_FAIL(case_expr->add_when_param_expr(when_expr))) { LOG_WARN("failed to add when param expr", K(ret)); } else if (OB_FAIL(case_expr->add_then_param_expr(one_expr))) { LOG_WARN("failed to add one expr", K(ret)); } else if (FALSE_IT(case_expr->set_default_param_expr(zero_expr))) { // do nothing } else if (OB_FAIL(expr_factory->create_raw_expr(T_FUN_SUM, sum_expr))) { LOG_WARN("failed to create new aggr expr", K(ret)); } else if (OB_ISNULL(sum_expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("sum expr is null", K(ret)); } else if (OB_FAIL(ObRawExprUtils::build_const_int_expr(*expr_factory, ObIntType, 0L, equal_value))) { LOG_WARN("faield to build const int expr", K(ret)); } else if (OB_FAIL(sum_expr->add_real_param_expr(case_expr))) { LOG_WARN("failed to add real param expr", K(ret)); } else if (OB_FAIL(ObRawExprUtils::create_double_op_expr( *expr_factory, ctx_->session_info_, T_OP_EQ, equal_expr, sum_expr, equal_value))) { LOG_WARN("failed to create equal expr", K(ret)); } else if (OB_FAIL(equal_expr->formalize(ctx_->session_info_))) { LOG_WARN("failed to formalize equal expr", K(ret)); } else if (OB_FAIL(equal_expr->replace_expr(old_cols, new_cols))) { LOG_WARN("failed to replace expr", K(ret)); } else if (OB_FAIL(new_exist_stmt->add_agg_item(*sum_expr))) { LOG_WARN("failed to add aggr item", K(ret)); } else if (OB_FAIL(new_exist_stmt->add_having_expr(equal_expr))) { LOG_WARN("failed to add having expr", K(ret)); } } return ret; } int ObTransformSubqueryCoalesce::merge_any_all_subqueries(ObQueryRefRawExpr* any_query_ref, ObQueryRefRawExpr* all_query_ref, TransformParam& trans_param, ObRawExpr*& new_any_all_query) { int ret = OB_SUCCESS; ObRawExprFactory* expr_factory = NULL; ObStmtFactory* stmt_factory = NULL; ObSEArray old_cols; ObSEArray new_cols; ObSEArray extra_conds; ObQueryRefRawExpr* new_query_ref = NULL; ObSelectStmt* any_stmt = NULL; ObSelectStmt* all_stmt = NULL; ObSelectStmt* new_any_stmt = NULL; const ObStmtMapInfo& map_info = trans_param.map_info_; if (OB_ISNULL(ctx_) || OB_ISNULL(expr_factory = ctx_->expr_factory_) || OB_ISNULL(stmt_factory = ctx_->stmt_factory_) || OB_ISNULL(any_query_ref) || OB_ISNULL(all_query_ref) || OB_ISNULL(any_stmt = any_query_ref->get_ref_stmt()) || OB_ISNULL(all_stmt = all_query_ref->get_ref_stmt()) || OB_UNLIKELY(map_info.cond_map_.count() != all_stmt->get_condition_size()) || OB_UNLIKELY(map_info.table_map_.count() != all_stmt->get_table_size())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("any/all exprs are not valid", K(ret), K(expr_factory), K(stmt_factory), K(any_query_ref), K(all_query_ref), K(any_stmt), K(all_stmt)); } else if (OB_FAIL(ObRawExprUtils::copy_expr( *expr_factory, trans_param.any_expr_, new_any_all_query, COPY_REF_DEFAULT))) { LOG_WARN("failed to copy any expr", K(ret)); } else if (OB_FAIL(expr_factory->create_raw_expr(T_INVALID, new_query_ref))) { LOG_WARN("failed to create query ref expr", K(ret)); } else if (OB_FAIL(new_query_ref->assign(*any_query_ref))) { LOG_WARN("failed to assign query ref expr", K(ret)); } else if (OB_FAIL( ObTransformUtils::copy_stmt(*stmt_factory, any_stmt, reinterpret_cast(new_any_stmt)))) { LOG_WARN("failed to copy any stmt", K(ret)); } else if (OB_FAIL(new_any_stmt->adjust_statement_id())) { LOG_WARN("failed to adjust stmt id", K(ret)); } else { new_query_ref->set_ref_stmt(new_any_stmt); new_any_all_query->get_param_expr(1) = new_query_ref; } for (int64_t i = 0; OB_SUCC(ret) && i < all_stmt->get_condition_size(); ++i) { ObRawExpr* new_cond_expr = NULL; if (map_info.cond_map_.at(i) >= 0 && map_info.cond_map_.at(i) < new_any_stmt->get_condition_size()) { // both stmt has the condition } else if (OB_FAIL(ObRawExprUtils::copy_expr( *expr_factory, all_stmt->get_condition_expr(i), new_cond_expr, COPY_REF_DEFAULT))) { LOG_WARN("failed to copy condition", K(ret)); } else if (OB_FAIL(extra_conds.push_back(new_cond_expr))) { LOG_WARN("failed to push back condition", K(ret)); } } for (int64_t i = 0; OB_SUCC(ret) && i < all_stmt->get_column_size(); ++i) { ColumnItem& col_item = all_stmt->get_column_items().at(i); ObColumnRefRawExpr* col_expr = all_stmt->get_column_items().at(i).expr_; ObRawExpr* new_expr = NULL; TableItem* new_table_item = NULL; int64_t idx = all_stmt->get_table_bit_index(col_item.table_id_) - 1; if (OB_UNLIKELY(idx < 0 || idx >= map_info.table_map_.count() || map_info.table_map_.at(idx) < 0 || map_info.table_map_.at(idx) >= new_any_stmt->get_table_size() || OB_ISNULL(new_table_item = new_any_stmt->get_table_item(map_info.table_map_.at(idx))))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table is not mapped", K(ret), K(idx)); } else if (OB_NOT_NULL( new_expr = new_any_stmt->get_column_expr_by_id(new_table_item->table_id_, col_item.column_id_))) { // do nothing } else if (OB_FAIL(ObRawExprUtils::copy_expr(*expr_factory, col_item.expr_, new_expr, COPY_REF_SHARED))) { LOG_WARN("failed to copy expr", K(ret)); } else { ColumnItem new_col_item; new_col_item.table_id_ = new_table_item->table_id_; new_col_item.column_id_ = col_item.column_id_; new_col_item.column_name_ = col_item.column_name_; new_col_item.expr_ = static_cast(new_expr); new_col_item.expr_->set_table_id(new_table_item->table_id_); new_col_item.expr_->set_table_name(new_table_item->table_name_); if (OB_FAIL(new_any_stmt->add_column_item(new_col_item))) { LOG_WARN("failed to add column item", K(ret)); } } if (OB_SUCC(ret)) { if (OB_FAIL(old_cols.push_back(col_expr))) { LOG_WARN("failed to append column expr", K(ret)); } else if (OB_FAIL(new_cols.push_back(new_expr))) { LOG_WARN("failed to append column expr", K(ret)); } } } if (OB_SUCC(ret)) { // create lnnvl exprs ObRawExpr* and_expr = NULL; ObRawExpr* lnnvl_expr = NULL; if (OB_FAIL(create_and_expr(extra_conds, and_expr))) { LOG_WARN("failed to create and expr", K(ret)); } else if (OB_FAIL(ObRawExprUtils::build_lnnvl_expr(*expr_factory, and_expr, lnnvl_expr))) { LOG_WARN("failed to build lnnvl expr", K(ret)); } else if (OB_FAIL(lnnvl_expr->formalize(ctx_->session_info_))) { LOG_WARN("failed to formalize lnnvl expr expr", K(ret)); } else if (OB_FAIL(lnnvl_expr->replace_expr(old_cols, new_cols))) { LOG_WARN("failed to replace expr", K(ret)); } else if (OB_FAIL(new_any_stmt->add_condition_expr(lnnvl_expr))) { LOG_WARN("failed to add having expr", K(ret)); } } return ret; } int ObTransformSubqueryCoalesce::create_and_expr(const ObIArray& params, ObRawExpr*& ret_expr) { int ret = OB_SUCCESS; ObRawExprFactory* factory = NULL; ObOpRawExpr* and_expr = NULL; ret_expr = NULL; if (OB_ISNULL(ctx_) || OB_ISNULL(factory = ctx_->expr_factory_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("params have null", K(ret), K(ctx_), K(factory)); } else if (params.count() == 0) { // do nothing } else if (params.count() == 1) { ret_expr = params.at(0); } else if (OB_FAIL(factory->create_raw_expr(T_OP_AND, and_expr))) { LOG_WARN("failed to create and expr", K(ret)); } else if (OB_ISNULL(and_expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("and expr is null", K(ret)); } else if (OB_FAIL(and_expr->get_param_exprs().assign(params))) { LOG_WARN("failed to assign params", K(ret)); } else { ret_expr = and_expr; } return ret; } ObQueryRefRawExpr* ObTransformSubqueryCoalesce::get_exists_query_expr(ObRawExpr* expr) { ObQueryRefRawExpr* ret_expr = NULL; if (OB_ISNULL(expr) || OB_UNLIKELY(expr->get_expr_type() != T_OP_EXISTS && expr->get_expr_type() != T_OP_NOT_EXISTS) || OB_ISNULL(expr->get_param_expr(0)) || OB_UNLIKELY(!expr->get_param_expr(0)->is_query_ref_expr())) { // do nothing } else { ret_expr = static_cast(expr->get_param_expr(0)); } return ret_expr; } ObQueryRefRawExpr* ObTransformSubqueryCoalesce::get_any_all_query_expr(ObRawExpr* expr) { ObQueryRefRawExpr* ret_expr = NULL; ObOpRawExpr* subquey_op = NULL; if (OB_ISNULL(expr) || OB_UNLIKELY(!expr->has_flag(IS_WITH_ANY) && !expr->has_flag(IS_WITH_ALL))) { // do nothing } else { subquey_op = static_cast(expr); if (OB_ISNULL(subquey_op->get_param_expr(1)) || OB_UNLIKELY(!subquey_op->get_param_expr(1)->is_query_ref_expr())) { /*do nothing*/ } else { ret_expr = static_cast(subquey_op->get_param_expr(1)); } } return ret_expr; } ObRawExpr* ObTransformSubqueryCoalesce::get_any_all_left_hand_expr(ObRawExpr* expr) { ObRawExpr* left_hand = NULL; ObOpRawExpr* subquey_op = NULL; if (OB_ISNULL(expr) || OB_UNLIKELY(!expr->has_flag(IS_WITH_ANY) && !expr->has_flag(IS_WITH_ALL))) { // do nothing } else { subquey_op = static_cast(expr); if (OB_ISNULL(subquey_op->get_param_expr(0))) { /*do nothing*/ } else { left_hand = subquey_op->get_param_expr(0); } } return left_hand; } int ObTransformSubqueryCoalesce::make_false(ObIArray& conds) { int ret = OB_SUCCESS; ObRawExpr* false_expr = NULL; conds.reset(); if (OB_ISNULL(ctx_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("transform context is null", K(ret)); } else if (OB_FAIL(ObRawExprUtils::build_const_bool_expr(ctx_->expr_factory_, false_expr, false))) { LOG_WARN("failed to build const bool expr", K(ret)); } else if (OB_FAIL(conds.push_back(false_expr))) { LOG_WARN("failed to push back false expr", K(ret)); } return ret; }