diff --git a/src/sql/resolver/dml/ob_dml_resolver.cpp b/src/sql/resolver/dml/ob_dml_resolver.cpp index b9c59dc125..b38548739c 100755 --- a/src/sql/resolver/dml/ob_dml_resolver.cpp +++ b/src/sql/resolver/dml/ob_dml_resolver.cpp @@ -1555,7 +1555,8 @@ int ObDMLResolver::resolve_sql_expr(const ParseNode &node, ObRawExpr *&expr, !params_.is_resolve_table_function_expr_ && !expr->has_flag(CNT_OUTER_JOIN_SYMBOL)) { bool is_new = false; - if (OB_FAIL(expr_resv_ctx_.get_shared_instance(expr, expr, is_new))) { + bool dummp_bool = false; + if (OB_FAIL(expr_resv_ctx_.get_shared_instance(expr, expr, is_new, dummp_bool))) { LOG_WARN("failed to get shared instance", K(ret)); } } diff --git a/src/sql/resolver/expr/ob_shared_expr_resolver.cpp b/src/sql/resolver/expr/ob_shared_expr_resolver.cpp index 723bb3cfb6..b347536616 100644 --- a/src/sql/resolver/expr/ob_shared_expr_resolver.cpp +++ b/src/sql/resolver/expr/ob_shared_expr_resolver.cpp @@ -143,7 +143,8 @@ int ObSharedExprResolver::add_new_instance(ObRawExprEntry &entry) int ObSharedExprResolver::get_shared_instance(ObRawExpr *expr, ObRawExpr *&shared_expr, - bool &is_new) + bool &is_new, + bool &disable_share_expr) { int ret = OB_SUCCESS; shared_expr = NULL; @@ -152,34 +153,37 @@ int ObSharedExprResolver::get_shared_instance(ObRawExpr *expr, if (OB_ISNULL(expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("expr is null", K(ret), K(expr)); - } else if (!expr->is_aggr_expr() && !expr->is_win_func_expr() && - T_OP_CASE != expr->get_expr_type()) { + } else if (is_blacklist_share_const(*expr)) { + disable_share_const_level_++; + } + if (OB_FAIL(ret) || is_blacklist_share_child(*expr)) { + } else { + bool has_questionmark = false; for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); ++i) { ObRawExpr *old_param_expr = expr->get_param_expr(i); ObRawExpr *new_param_expr = NULL; bool is_param_new = false; - if (old_param_expr->get_expr_type() == T_QUESTIONMARK || - (expr->get_expr_type() == T_FUN_SYS_CAST && i == 1)) { + bool disable_share_child = false; + if (old_param_expr->get_expr_type() == T_QUESTIONMARK) { + if (old_param_expr->has_flag(IS_STATIC_PARAM) && disable_share_const_level_ > 0) { + disable_share_expr = true; + } + } else if (expr->get_expr_type() == T_FUN_SYS_CAST && i == 1) { // skip exec var and question mark } else if (OB_FAIL(SMART_CALL(get_shared_instance(old_param_expr, new_param_expr, - is_param_new)))) { + is_param_new, + disable_share_child)))) { LOG_WARN("failed to get shared instance", K(ret)); } else { expr->get_param_expr(i) = new_param_expr; has_new_param = has_new_param || is_param_new; + disable_share_expr |= disable_share_child; } } } if (OB_SUCC(ret)) { - if (expr->is_column_ref_expr() || - expr->is_aggr_expr() || - expr->is_win_func_expr() || - expr->is_query_ref_expr() || - expr->is_exec_param_expr() || - expr->is_pseudo_column_expr() || - expr->get_expr_type() == T_OP_ROW || - expr->get_expr_type() == T_QUESTIONMARK) { + if (is_blacklist_share_expr(*expr) || disable_share_expr) { shared_expr = expr; } else { ObRawExprEntry entry(expr, get_scope_id(), hash_expr_tree(expr, get_scope_id())); @@ -196,6 +200,9 @@ int ObSharedExprResolver::get_shared_instance(ObRawExpr *expr, is_new = true; } } + if (is_blacklist_share_const(*expr)) { + disable_share_const_level_--; + } } return ret; } diff --git a/src/sql/resolver/expr/ob_shared_expr_resolver.h b/src/sql/resolver/expr/ob_shared_expr_resolver.h index e83f2ef217..e5d45cf8f1 100644 --- a/src/sql/resolver/expr/ob_shared_expr_resolver.h +++ b/src/sql/resolver/expr/ob_shared_expr_resolver.h @@ -59,14 +59,16 @@ public: ObSharedExprResolver(ObQueryCtx *query_ctx) : allocator_("MergeSharedExpr"), scope_id_(0), - query_ctx_(query_ctx) + query_ctx_(query_ctx), + disable_share_const_level_(0) {} virtual ~ObSharedExprResolver(); int get_shared_instance(ObRawExpr *expr, ObRawExpr *&shared_expr, - bool &is_new); + bool &is_new, + bool &disable_share_expr); int add_new_instance(ObRawExprEntry &entry); @@ -82,7 +84,25 @@ private: int inner_get_shared_expr(ObRawExprEntry &entry, ObRawExpr *&new_expr); - + inline bool is_blacklist_share_expr(const ObRawExpr &expr) + { + return expr.is_column_ref_expr() || + expr.is_aggr_expr() || + expr.is_win_func_expr() || + expr.is_query_ref_expr() || + expr.is_exec_param_expr() || + expr.is_pseudo_column_expr() || + expr.get_expr_type() == T_OP_ROW || + expr.get_expr_type() == T_QUESTIONMARK; + } + inline bool is_blacklist_share_child(const ObRawExpr &expr) + { + return expr.is_aggr_expr() || expr.is_win_func_expr() || T_OP_CASE == expr.get_expr_type(); + } + inline bool is_blacklist_share_const(const ObRawExpr &expr) + { + return T_OP_OR == expr.get_expr_type() || T_OP_AND == expr.get_expr_type(); + } private: typedef ObSEArray SharedExprs; @@ -92,6 +112,7 @@ private: uint64_t scope_id_; ObQueryCtx *query_ctx_; + int64_t disable_share_const_level_; }; } diff --git a/src/sql/rewrite/ob_transform_simplify_expr.cpp b/src/sql/rewrite/ob_transform_simplify_expr.cpp index eb8085313b..782a539f78 100644 --- a/src/sql/rewrite/ob_transform_simplify_expr.cpp +++ b/src/sql/rewrite/ob_transform_simplify_expr.cpp @@ -2473,7 +2473,9 @@ int ObTransformSimplifyExpr::do_canonicalize(ObDMLStmt *stmt, ObIArrayget_query_ctx(), + conditions, + remove_duplicate_happend))) { LOG_WARN("remove_duplicate_exprs failed", K(ret)); } else if (OB_FAIL(pull_similar_expr(stmt, conditions, pull_similar_happend))) { LOG_WARN("pull_similar_expr failed", K(ret)); @@ -2817,14 +2819,17 @@ int ObTransformSimplifyExpr::get_opposite_op(ObItemType type, ObItemType& opposi return ret; } -int ObTransformSimplifyExpr::remove_duplicate_exprs(ObIArray &conditions, bool &trans_happened) +int ObTransformSimplifyExpr::remove_duplicate_exprs(ObQueryCtx* query_ctx, + ObIArray &conditions, + bool &trans_happened) { /* basic case * A and A -> A * A or A -> A */ int ret = OB_SUCCESS; - for (int64_t i = 0; OB_SUCC(ret) && i < conditions.count(); i++) { + const int64_t param_count = conditions.count(); + for (int64_t i = 0; OB_SUCC(ret) && i < param_count; i++) { if (OB_ISNULL(conditions.at(i))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpect null pointer error", K(conditions.at(i)), K(ret)); @@ -2832,18 +2837,45 @@ int ObTransformSimplifyExpr::remove_duplicate_exprs(ObIArray &condit LOG_WARN("do_remove fail", K(conditions.at(i)), K(ret)); } } - if (OB_SUCC(ret) && conditions.count() > 1) { + if (OB_SUCC(ret) && param_count > 1 && param_count <= 100) { //select * from t1 where c1 > 1 and c1 > 1 //like above stmt, and expr in level 0 is process here ObSEArray param_conds; - if (OB_FAIL(append_array_no_dup(param_conds, conditions))) { - LOG_WARN("fail to append_array_no_dup", K(ret)); - } else if (param_conds.count() == conditions.count()) { - //do nothing - } else if (OB_FAIL(conditions.assign(param_conds))) { - LOG_WARN("assign array failed", K(ret)); + ObQuestionmarkEqualCtx cmp_ctx(true); + + if (OB_ISNULL(query_ctx)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null pointer error", K(ret)); + } else if (OB_FAIL(param_conds.assign(conditions))) { + LOG_WARN("failed to assign array", K(ret)); } else { - trans_happened = true; + for (int64_t i = param_count - 1; OB_SUCC(ret) && i >= 1; i--) { + for (int64_t j = 0; OB_SUCC(ret) && j < i; j++) { + if (param_conds.at(i)->same_as(*param_conds.at(j), &cmp_ctx)) { + if (OB_FAIL(param_conds.remove(i))) { + LOG_WARN("failed to remove", K(ret)); + } else if (!cmp_ctx.equal_pairs_.empty()) { + if (OB_FAIL(append(query_ctx->all_equal_param_constraints_, + cmp_ctx.equal_pairs_))) { + LOG_WARN("failed to append expr", K(ret)); + } else { + cmp_ctx.equal_pairs_.reset(); + } + } + break; + } else if (!cmp_ctx.equal_pairs_.empty()) { + cmp_ctx.equal_pairs_.reset(); + } + } + } + if (OB_FAIL(ret)) { + } else if (param_conds.count() == conditions.count()) { + //do nothing + } else if (OB_FAIL(conditions.assign(param_conds))) { + LOG_WARN("assign array failed", K(ret)); + } else { + trans_happened = true; + } } } if (OB_SUCC(ret) && trans_happened) { @@ -2902,11 +2934,11 @@ int ObTransformSimplifyExpr::pull_similar_expr(ObDMLStmt *stmt, { /* * example1: - * c1 and c5 or (c1 and c2) or (c1 and c3 and c4) + * (c1 and c5) or (c1 and c2) or (c1 and c3 and c4) * param_sets<,,> * intersection : * param_sets after remove intersection: <,,> - * build new expr : c1 and (c5 or or c2 c3 and c4) + * build new expr : c1 and (c5 or c2 or (c3 and c4)) * * example2: * c1 or (c1 and c2) or (c1 and c3 and c4) @@ -3095,18 +3127,13 @@ int ObTransformSimplifyExpr::get_intersection(ObDMLStmt *stmt, } else if (OB_FAIL(params.assign(temp_result))) { LOG_WARN("fail to assign array", K(ret)); } - } - if (OB_SUCC(ret) && is_valid) { - if (OB_FAIL(append(ctx_->equal_param_constraints_, context.equal_param_info_))) { - context.equal_param_info_.reset(); - ret = OB_SIZE_OVERFLOW == context.error_code_; - LOG_WARN("append equal param info failed", K(ret)); - } else if (OB_FAIL(intersection.assign(params))) { - LOG_WARN("fail to assign array", K(ret)); - } else { + if (OB_SUCC(ret)) { context.equal_param_info_.reset(); } } + if (OB_SUCC(ret) && is_valid && OB_FAIL(intersection.assign(params))) { + LOG_WARN("fail to assign array", K(ret)); + } return ret; } @@ -3114,16 +3141,25 @@ int ObTransformSimplifyExpr::remove_intersect_item(ObIArray &intersection) { int ret = OB_SUCCESS; + ObStmtCompareContext context; for (int64_t i = 0; OB_SUCC(ret) && i < params_sets.count(); i++) { ObSEArray temp_result; for (int64_t j = 0; OB_SUCC(ret) && j < params_sets.at(i).count(); j++) { bool find = false; - if (OB_FAIL(ObTransformUtils::find_expr(intersection, params_sets.at(i).at(j), find))) { + if (OB_FAIL(ObTransformUtils::find_expr(intersection, params_sets.at(i).at(j), find, &context))) { LOG_WARN("failed to find expr", K(ret)); } else if (find) { - // do nothing + if (!context.equal_param_info_.empty()) { + if (OB_FAIL(append(ctx_->equal_param_constraints_, context.equal_param_info_))) { + ret = OB_SIZE_OVERFLOW == context.error_code_; + LOG_WARN("append equal param info failed", K(ret)); + } + context.equal_param_info_.reset(); + } } else if (OB_FAIL(temp_result.push_back(params_sets.at(i).at(j)))) { LOG_WARN("failed to push back expr", K(ret)); + } else if (!context.equal_param_info_.empty()) { + context.equal_param_info_.reset(); } } if (OB_FAIL(ret)) { diff --git a/src/sql/rewrite/ob_transform_simplify_expr.h b/src/sql/rewrite/ob_transform_simplify_expr.h index 29e1e5b1a1..e298852c21 100644 --- a/src/sql/rewrite/ob_transform_simplify_expr.h +++ b/src/sql/rewrite/ob_transform_simplify_expr.h @@ -182,7 +182,7 @@ private: bool is_left); int get_opposite_op(ObItemType type, ObItemType& opposit_type); - int remove_duplicate_exprs(ObIArray &conditions, bool &trans_happened); + int remove_duplicate_exprs(ObQueryCtx* query_ctx, ObIArray &conditions, bool &trans_happened); int do_remove(ObRawExpr* &expr, bool &trans_happened); int pull_similar_expr(ObDMLStmt *stmt, ObIArray &conditions, bool &trans_happened); int recursive_pull_similar(ObDMLStmt *stmt, ObRawExpr* &expr, bool &trans_happened);