fix an exec_param and a expr copy_on_replace bugs
This commit is contained in:
		| @ -637,6 +637,7 @@ int ObLogSubPlanFilter::replace_nested_subquery_exprs(ObRawExprReplacer &replace | |||||||
|   } |   } | ||||||
|   for (int64_t i = 0; OB_SUCC(ret) && i < subquery_exprs_.count(); ++i) { |   for (int64_t i = 0; OB_SUCC(ret) && i < subquery_exprs_.count(); ++i) { | ||||||
|     ObRawExpr *expr = subquery_exprs_.at(i); |     ObRawExpr *expr = subquery_exprs_.at(i); | ||||||
|  |     int64_t ref_id = subquery_exprs_.at(i)->get_ref_id(); | ||||||
|     if (ObOptimizerUtil::find_item(plan->get_onetime_query_refs(), expr)) { |     if (ObOptimizerUtil::find_item(plan->get_onetime_query_refs(), expr)) { | ||||||
|       // do not replace onetime expr ref query, only adjust nested subquery |       // do not replace onetime expr ref query, only adjust nested subquery | ||||||
|     } else if (OB_FAIL(replace_expr_action(replacer, expr))) { |     } else if (OB_FAIL(replace_expr_action(replacer, expr))) { | ||||||
| @ -648,6 +649,7 @@ int ObLogSubPlanFilter::replace_nested_subquery_exprs(ObRawExprReplacer &replace | |||||||
|       LOG_WARN("unexpected expr type", K(ret)); |       LOG_WARN("unexpected expr type", K(ret)); | ||||||
|     } else { |     } else { | ||||||
|       subquery_exprs_.at(i) = static_cast<ObQueryRefRawExpr*>(expr); |       subquery_exprs_.at(i) = static_cast<ObQueryRefRawExpr*>(expr); | ||||||
|  |       subquery_exprs_.at(i)->set_ref_id(ref_id); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   return ret; |   return ret; | ||||||
|  | |||||||
| @ -64,6 +64,8 @@ int ObAggrExprPushUpAnalyzer::analyze_and_push_up_aggr_expr(ObRawExprFactory &ex | |||||||
|   } else if (OB_FAIL(ObTransformUtils::decorrelate(reinterpret_cast<ObRawExpr *&>(aggr_expr), |   } else if (OB_FAIL(ObTransformUtils::decorrelate(reinterpret_cast<ObRawExpr *&>(aggr_expr), | ||||||
|                                                    final_exec_params))) { |                                                    final_exec_params))) { | ||||||
|     LOG_WARN("failed to decorrelate exec params", K(ret)); |     LOG_WARN("failed to decorrelate exec params", K(ret)); | ||||||
|  |   } else if (OB_FAIL(replace_final_exec_param_in_aggr(final_exec_params, param_query_refs, expr_factory))) { | ||||||
|  |     LOG_WARN("failed to replace real exec param in aggr", K(ret)); | ||||||
|   } |   } | ||||||
|   if (OB_SUCC(ret)) { |   if (OB_SUCC(ret)) { | ||||||
|     if (OB_FAIL(final_aggr_resolver->add_aggr_expr(aggr_expr))) { |     if (OB_FAIL(final_aggr_resolver->add_aggr_expr(aggr_expr))) { | ||||||
| @ -444,5 +446,136 @@ int ObAggrExprPushUpAnalyzer::get_exec_params(ObDMLResolver *resolver, | |||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int ObAggrExprPushUpAnalyzer::replace_final_exec_param_in_aggr(const ObIArray<ObExecParamRawExpr *> &exec_params, | ||||||
|  |                                                               ObIArray<ObQueryRefRawExpr *> ¶m_query_refs, | ||||||
|  |                                                               ObRawExprFactory &expr_factory) | ||||||
|  | { | ||||||
|  |   int ret = OB_SUCCESS; | ||||||
|  |   ObSEArray<ObExecParamRawExpr *, 4> new_execs; | ||||||
|  |   for (int64_t i = 0; OB_SUCC(ret) && i < exec_params.count(); ++i) { | ||||||
|  |     ObExecParamRawExpr *new_expr = NULL; | ||||||
|  |     if (OB_FAIL(ObRawExprUtils::create_new_exec_param(expr_factory, | ||||||
|  |                                                       exec_params.at(i)->get_ref_expr(), | ||||||
|  |                                                       new_expr, | ||||||
|  |                                                       false))) { | ||||||
|  |       LOG_WARN("failed to create new exec param", K(ret)); | ||||||
|  |     } else if (OB_FAIL(new_execs.push_back(static_cast<ObExecParamRawExpr *>(new_expr)))) { | ||||||
|  |       LOG_WARN("failed to push back", K(ret)); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   if (OB_SUCC(ret)) { | ||||||
|  |     ObStmtExecParamReplacer replacer; | ||||||
|  |     replacer.set_relation_scope(); | ||||||
|  |     if (OB_FAIL(replacer.add_replace_exprs(exec_params, new_execs))) { | ||||||
|  |       LOG_WARN("failed to add replace exprs", K(ret)); | ||||||
|  |     } else { | ||||||
|  |       for (int64_t i = 0; OB_SUCC(ret) && i < param_query_refs.count(); i++) { | ||||||
|  |         if (OB_FAIL(replacer.do_visit(reinterpret_cast<ObRawExpr *&>(param_query_refs.at(i))))) { | ||||||
|  |           LOG_WARN("failed to replace exec param", K(ret)); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int ObStmtExecParamReplacer::check_need_replace(const ObRawExpr *old_expr, | ||||||
|  |                                                 ObRawExpr *&new_expr, | ||||||
|  |                                                 bool &need_replace) | ||||||
|  | { | ||||||
|  |   int ret = OB_SUCCESS; | ||||||
|  |   uint64_t key = reinterpret_cast<uint64_t>(old_expr); | ||||||
|  |   uint64_t val = 0; | ||||||
|  |   need_replace = false; | ||||||
|  |   if (OB_UNLIKELY(!expr_replace_map_.created())) { | ||||||
|  |     // do nothing | ||||||
|  |   } else if (OB_FAIL(expr_replace_map_.get_refactored(key, val))) { | ||||||
|  |     if (OB_HASH_NOT_EXIST == ret) { | ||||||
|  |       ret = OB_SUCCESS; | ||||||
|  |     } else { | ||||||
|  |       LOG_WARN("failed to get expr from hash map", K(ret)); | ||||||
|  |     } | ||||||
|  |   } else { | ||||||
|  |     need_replace = true; | ||||||
|  |     new_expr = reinterpret_cast<ObRawExpr *>(val); | ||||||
|  |   } | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int ObStmtExecParamReplacer::add_replace_exprs(const ObIArray<ObExecParamRawExpr *> &from_exprs, | ||||||
|  |                                                const ObIArray<ObExecParamRawExpr *> &to_exprs) | ||||||
|  | { | ||||||
|  |   int ret = OB_SUCCESS; | ||||||
|  |   int64_t bucket_size = MAX(from_exprs.count(), 64); | ||||||
|  |   if (OB_UNLIKELY(from_exprs.count() != to_exprs.count())) { | ||||||
|  |     ret = OB_ERR_UNEXPECTED; | ||||||
|  |     LOG_WARN("expr size mismatch", K(from_exprs.count()), K(to_exprs.count()), K(ret)); | ||||||
|  |   } else if (expr_replace_map_.created()) { | ||||||
|  |     /* do nothing */ | ||||||
|  |   } else if (OB_FAIL(expr_replace_map_.create(bucket_size, ObModIds::OB_SQL_COMPILE))) { | ||||||
|  |     LOG_WARN("failed to create expr map", K(ret)); | ||||||
|  |   } else if (OB_FAIL(to_exprs_.create(bucket_size))) { | ||||||
|  |     LOG_WARN("failed to create expr set", K(ret)); | ||||||
|  |   } | ||||||
|  |   const ObRawExpr *from_expr = NULL; | ||||||
|  |   const ObRawExpr *to_expr = NULL; | ||||||
|  |   for (int64_t i = 0; OB_SUCC(ret) && i < from_exprs.count(); ++i) { | ||||||
|  |     bool is_existed = false; | ||||||
|  |     ObRawExpr *new_expr = NULL; | ||||||
|  |     if (OB_ISNULL(from_expr = from_exprs.at(i)) || OB_ISNULL(to_expr = to_exprs.at(i))) { | ||||||
|  |       ret = OB_ERR_UNEXPECTED; | ||||||
|  |       LOG_WARN("unexpected null expr", KP(from_expr), KP(to_expr), K(ret)); | ||||||
|  |     } else if (OB_FAIL(check_need_replace(from_expr, new_expr, is_existed))) { | ||||||
|  |       LOG_WARN("failed to check need replace", K(ret)); | ||||||
|  |     } else if (is_existed) { | ||||||
|  |       /* do nothing */ | ||||||
|  |     } else if (OB_FAIL(expr_replace_map_.set_refactored(reinterpret_cast<uint64_t>(from_expr), | ||||||
|  |                                                         reinterpret_cast<uint64_t>(to_expr)))) { | ||||||
|  |       LOG_WARN("failed to add replace expr into map", K(ret)); | ||||||
|  |     } else if (OB_FAIL(to_exprs_.set_refactored(reinterpret_cast<uint64_t>(to_expr)))) { | ||||||
|  |       LOG_WARN("failed to add replace expr into set", K(ret)); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int ObStmtExecParamReplacer::do_visit(ObRawExpr *&expr) | ||||||
|  | { | ||||||
|  |   int ret = OB_SUCCESS; | ||||||
|  |   bool is_happended = false; | ||||||
|  |   if (OB_ISNULL(expr)) { | ||||||
|  |     ret = OB_ERR_UNEXPECTED; | ||||||
|  |     LOG_WARN("expr is null", K(ret), K(expr)); | ||||||
|  |   } else if (expr->is_exec_param_expr()) { | ||||||
|  |     bool need_replace = false; | ||||||
|  |     ObRawExpr *to_expr; | ||||||
|  |     if (OB_FAIL(check_need_replace(expr, to_expr, need_replace))) { | ||||||
|  |       LOG_WARN("failed to check need replace", K(ret)); | ||||||
|  |     } else if (need_replace) { | ||||||
|  |       expr = to_expr; | ||||||
|  |     } | ||||||
|  |   } else if (expr->is_query_ref_expr()) { | ||||||
|  |     ObQueryRefRawExpr *query_ref_expr = static_cast<ObQueryRefRawExpr*>(expr); | ||||||
|  |     for (int64_t i = 0; OB_SUCC(ret) && i < query_ref_expr->get_param_count(); ++i) { | ||||||
|  |       if (OB_FAIL(SMART_CALL(do_visit(reinterpret_cast<ObRawExpr *&>( | ||||||
|  |                                                       query_ref_expr->get_exec_params().at(i)))))) { | ||||||
|  |         LOG_WARN("failed to remove const exec param", K(ret)); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     if (NULL == query_ref_expr->get_ref_stmt()) { | ||||||
|  |       /* ref_stmt may has not been resolve yet */ | ||||||
|  |     } else if (OB_FAIL(SMART_CALL(query_ref_expr->get_ref_stmt()->iterate_stmt_expr(*this)))) { | ||||||
|  |       LOG_WARN("failed to iterator stmt expr", K(ret)); | ||||||
|  |     } | ||||||
|  |   } else if (expr->has_flag(CNT_SUB_QUERY)) { | ||||||
|  |     for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); i++) { | ||||||
|  |       if (OB_FAIL(SMART_CALL(do_visit(expr->get_param_expr(i))))) { | ||||||
|  |         LOG_WARN("failed to do replace exec param", K(ret)); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
| }  // namespace sql | }  // namespace sql | ||||||
| }  // namespace oceanbase | }  // namespace oceanbase | ||||||
|  | |||||||
| @ -15,6 +15,7 @@ | |||||||
| #include "lib/container/ob_array.h" | #include "lib/container/ob_array.h" | ||||||
| #include "sql/ob_sql_utils.h" | #include "sql/ob_sql_utils.h" | ||||||
| #include "sql/resolver/expr/ob_raw_expr.h" | #include "sql/resolver/expr/ob_raw_expr.h" | ||||||
|  | #include "sql/resolver/dml/ob_stmt_expr_visitor.h" | ||||||
| namespace oceanbase | namespace oceanbase | ||||||
| { | { | ||||||
| namespace sql | namespace sql | ||||||
| @ -23,6 +24,20 @@ class ObDMLResolver; | |||||||
| class ObAggFunRawExpr; | class ObAggFunRawExpr; | ||||||
| class ObSelectResolver; | class ObSelectResolver; | ||||||
| class ObSelectStmt; | class ObSelectStmt; | ||||||
|  |  | ||||||
|  | class ObStmtExecParamReplacer : public ObStmtExprVisitor | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |   ObStmtExecParamReplacer() {} | ||||||
|  |   virtual int do_visit(ObRawExpr *&expr) override; | ||||||
|  |   int add_replace_exprs(const ObIArray<ObExecParamRawExpr *> &from_exprs, | ||||||
|  |                         const ObIArray<ObExecParamRawExpr *> &to_exprs); | ||||||
|  |   int check_need_replace(const ObRawExpr *old_expr, ObRawExpr *&new_expr, bool &need_replace); | ||||||
|  | private: | ||||||
|  |   hash::ObHashSet<uint64_t> to_exprs_; | ||||||
|  |   hash::ObHashMap<uint64_t, uint64_t> expr_replace_map_; | ||||||
|  | }; | ||||||
|  |  | ||||||
| class ObAggrExprPushUpAnalyzer | class ObAggrExprPushUpAnalyzer | ||||||
| { | { | ||||||
| public: | public: | ||||||
| @ -63,7 +78,9 @@ private: | |||||||
|   int remove_alias_exprs(); |   int remove_alias_exprs(); | ||||||
|  |  | ||||||
|   int remove_alias_exprs(ObRawExpr* &expr); |   int remove_alias_exprs(ObRawExpr* &expr); | ||||||
|  |   int replace_final_exec_param_in_aggr(const ObIArray<ObExecParamRawExpr *> &exec_params, | ||||||
|  |                                        ObIArray<ObQueryRefRawExpr *> ¶m_query_refs, | ||||||
|  |                                        ObRawExprFactory &expr_factory); | ||||||
| private: | private: | ||||||
|   // contain current layer column (a real column or a alias select item) |   // contain current layer column (a real column or a alias select item) | ||||||
|   bool has_cur_layer_column_; |   bool has_cur_layer_column_; | ||||||
|  | |||||||
| @ -262,4 +262,4 @@ int ObStmtExecParamFormatter::do_formalize_exec_param(ObRawExpr *&expr, bool &is | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  | |||||||
| @ -65,6 +65,7 @@ public: | |||||||
|                         const ObIArray<ObRawExpr *> &to_exprs); |                         const ObIArray<ObRawExpr *> &to_exprs); | ||||||
|   int add_replace_exprs(const ObIArray<std::pair<ObRawExpr *, ObRawExpr *>> &to_replace_exprs); |   int add_replace_exprs(const ObIArray<std::pair<ObRawExpr *, ObRawExpr *>> &to_replace_exprs); | ||||||
|   int append_replace_exprs(const ObRawExprReplacer &other); |   int append_replace_exprs(const ObRawExprReplacer &other); | ||||||
|  |   int check_need_replace(const ObRawExpr *old_expr, ObRawExpr *&new_expr, bool &need_replace); | ||||||
|  |  | ||||||
| private: | private: | ||||||
|   // types and constants |   // types and constants | ||||||
| @ -76,9 +77,6 @@ private: | |||||||
|                               const bool overwrite, |                               const bool overwrite, | ||||||
|                               bool &is_existed); |                               bool &is_existed); | ||||||
|   int check_skip_expr(const ObRawExpr &expr, bool &skip_expr); |   int check_skip_expr(const ObRawExpr &expr, bool &skip_expr); | ||||||
|   int check_need_replace(const ObRawExpr *old_expr, |  | ||||||
|                          ObRawExpr *&new_expr, |  | ||||||
|                          bool &need_replace); |  | ||||||
|   // disallow copy |   // disallow copy | ||||||
|   DISALLOW_COPY_AND_ASSIGN(ObRawExprReplacer); |   DISALLOW_COPY_AND_ASSIGN(ObRawExprReplacer); | ||||||
|   // function members |   // function members | ||||||
|  | |||||||
| @ -4576,29 +4576,52 @@ int ObRawExprUtils::get_exec_param_expr(ObRawExprFactory &expr_factory, | |||||||
|   // we create a new one here |   // we create a new one here | ||||||
|   if (OB_SUCC(ret) && NULL == param_expr) { |   if (OB_SUCC(ret) && NULL == param_expr) { | ||||||
|     ObExecParamRawExpr *exec_param = NULL; |     ObExecParamRawExpr *exec_param = NULL; | ||||||
|     if (OB_FAIL(expr_factory.create_raw_expr(T_QUESTIONMARK, exec_param))) { |     if (OB_FAIL(ObRawExprUtils::create_new_exec_param(expr_factory, | ||||||
|       LOG_WARN("failed to create raw expr", K(ret)); |                                                       outer_val_expr, | ||||||
|     } else if (OB_ISNULL(exec_param)) { |                                                       exec_param, | ||||||
|       ret = OB_ERR_UNEXPECTED; |                                                       false))) { | ||||||
|       LOG_WARN("exec param is null", K(ret), K(exec_param)); |       LOG_WARN("failed to create new exec param", K(ret)); | ||||||
|     } else if (OB_FAIL(query_ref->add_exec_param_expr(exec_param))) { |     } else if (OB_FAIL(query_ref->add_exec_param_expr(exec_param))) { | ||||||
|       LOG_WARN("failed to add exec param expr", K(ret)); |       LOG_WARN("failed to add exec param expr", K(ret)); | ||||||
|     } else if (OB_FAIL(exec_param->set_enum_set_values(outer_val_expr->get_enum_set_values()))) { |  | ||||||
|       LOG_WARN("failed to set enum set values", K(ret)); |  | ||||||
|     } else if (OB_FAIL(exec_param->add_flag(IS_CONST))) { |  | ||||||
|       LOG_WARN("failed to add flag", K(ret)); |  | ||||||
|     } else if (OB_FAIL(exec_param->add_flag(IS_DYNAMIC_PARAM))) { |  | ||||||
|       LOG_WARN("failed to add flag", K(ret)); |  | ||||||
|     } else { |     } else { | ||||||
|       exec_param->set_ref_expr(outer_val_expr); |  | ||||||
|       exec_param->set_param_index(-1); |  | ||||||
|       exec_param->set_result_type(outer_val_expr->get_result_type()); |  | ||||||
|       param_expr = exec_param; |       param_expr = exec_param; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int ObRawExprUtils::create_new_exec_param(ObRawExprFactory &expr_factory, | ||||||
|  |                                           ObRawExpr *ref_expr, | ||||||
|  |                                           ObExecParamRawExpr *&exec_param, | ||||||
|  |                                           bool is_onetime /*=false*/) | ||||||
|  | { | ||||||
|  |   int ret = OB_SUCCESS; | ||||||
|  |   exec_param = NULL; | ||||||
|  |   if (OB_ISNULL(ref_expr)) { | ||||||
|  |     ret = OB_ERR_UNEXPECTED; | ||||||
|  |     LOG_WARN("expr is null", K(ret), K(ref_expr)); | ||||||
|  |   } else if (OB_FAIL(expr_factory.create_raw_expr(T_QUESTIONMARK, exec_param))) { | ||||||
|  |     LOG_WARN("failed to create exec param expr", K(ret)); | ||||||
|  |   } else if (OB_ISNULL(exec_param)) { | ||||||
|  |     ret = OB_ERR_UNEXPECTED; | ||||||
|  |     LOG_WARN("exec param is null", K(ret), K(exec_param)); | ||||||
|  |   } else if (OB_FAIL(exec_param->set_enum_set_values(ref_expr->get_enum_set_values()))) { | ||||||
|  |     LOG_WARN("failed to set enum set values", K(ret)); | ||||||
|  |   } else if (OB_FAIL(exec_param->add_flag(IS_CONST))) { | ||||||
|  |     LOG_WARN("failed to add flag", K(ret)); | ||||||
|  |   } else if (OB_FAIL(exec_param->add_flag(IS_DYNAMIC_PARAM))) { | ||||||
|  |     LOG_WARN("failed to add flag", K(ret)); | ||||||
|  |   } else { | ||||||
|  |     exec_param->set_ref_expr(ref_expr, is_onetime); | ||||||
|  |     exec_param->set_param_index(-1); | ||||||
|  |     exec_param->set_result_type(ref_expr->get_result_type()); | ||||||
|  |     if (is_onetime) { | ||||||
|  |       exec_param->add_flag(IS_ONETIME); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
| int ObRawExprUtils::create_new_exec_param(ObQueryCtx *query_ctx, | int ObRawExprUtils::create_new_exec_param(ObQueryCtx *query_ctx, | ||||||
|                                           ObRawExprFactory &expr_factory, |                                           ObRawExprFactory &expr_factory, | ||||||
|                                           ObRawExpr *&expr, |                                           ObRawExpr *&expr, | ||||||
|  | |||||||
| @ -557,11 +557,10 @@ public: | |||||||
|                                    ObRawExprFactory &expr_factory, |                                    ObRawExprFactory &expr_factory, | ||||||
|                                    ObRawExpr *&expr, |                                    ObRawExpr *&expr, | ||||||
|                                    bool is_onetime = false); |                                    bool is_onetime = false); | ||||||
|  |   static int create_new_exec_param(ObRawExprFactory &expr_factory, | ||||||
|   static int create_exec_param_expr(ObQueryCtx *query_ctx, |                                    ObRawExpr *ref_expr, | ||||||
|                                     ObRawExprFactory &expr_factory, |                                    ObExecParamRawExpr *&exec_param, | ||||||
|                                     ObRawExpr *&src_expr, |                                    bool is_onetime = false); | ||||||
|                                     std::pair<int64_t, ObRawExpr*> &init_expr); |  | ||||||
|   static int create_param_expr(ObRawExprFactory &expr_factory, int64_t param_idx, ObRawExpr *&expr); |   static int create_param_expr(ObRawExprFactory &expr_factory, int64_t param_idx, ObRawExpr *&expr); | ||||||
|   static int build_trim_expr(const share::schema::ObColumnSchemaV2 *column_schema, |   static int build_trim_expr(const share::schema::ObColumnSchemaV2 *column_schema, | ||||||
|                              ObRawExprFactory &expr_factory, |                              ObRawExprFactory &expr_factory, | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 jingtaoye35
					jingtaoye35