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) { | ||||
|     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)) { | ||||
|       // do not replace onetime expr ref query, only adjust nested subquery | ||||
|     } 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)); | ||||
|     } else { | ||||
|       subquery_exprs_.at(i) = static_cast<ObQueryRefRawExpr*>(expr); | ||||
|       subquery_exprs_.at(i)->set_ref_id(ref_id); | ||||
|     } | ||||
|   } | ||||
|   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), | ||||
|                                                    final_exec_params))) { | ||||
|     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_FAIL(final_aggr_resolver->add_aggr_expr(aggr_expr))) { | ||||
| @ -444,5 +446,136 @@ int ObAggrExprPushUpAnalyzer::get_exec_params(ObDMLResolver *resolver, | ||||
|   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 oceanbase | ||||
|  | ||||
| @ -15,6 +15,7 @@ | ||||
| #include "lib/container/ob_array.h" | ||||
| #include "sql/ob_sql_utils.h" | ||||
| #include "sql/resolver/expr/ob_raw_expr.h" | ||||
| #include "sql/resolver/dml/ob_stmt_expr_visitor.h" | ||||
| namespace oceanbase | ||||
| { | ||||
| namespace sql | ||||
| @ -23,6 +24,20 @@ class ObDMLResolver; | ||||
| class ObAggFunRawExpr; | ||||
| class ObSelectResolver; | ||||
| 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 | ||||
| { | ||||
| public: | ||||
| @ -63,7 +78,9 @@ private: | ||||
|   int remove_alias_exprs(); | ||||
|  | ||||
|   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: | ||||
|   // contain current layer column (a real column or a alias select item) | ||||
|   bool has_cur_layer_column_; | ||||
|  | ||||
| @ -262,4 +262,4 @@ int ObStmtExecParamFormatter::do_formalize_exec_param(ObRawExpr *&expr, bool &is | ||||
|     } | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -65,6 +65,7 @@ public: | ||||
|                         const ObIArray<ObRawExpr *> &to_exprs); | ||||
|   int add_replace_exprs(const ObIArray<std::pair<ObRawExpr *, ObRawExpr *>> &to_replace_exprs); | ||||
|   int append_replace_exprs(const ObRawExprReplacer &other); | ||||
|   int check_need_replace(const ObRawExpr *old_expr, ObRawExpr *&new_expr, bool &need_replace); | ||||
|  | ||||
| private: | ||||
|   // types and constants | ||||
| @ -76,9 +77,6 @@ private: | ||||
|                               const bool overwrite, | ||||
|                               bool &is_existed); | ||||
|   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_AND_ASSIGN(ObRawExprReplacer); | ||||
|   // function members | ||||
|  | ||||
| @ -4576,29 +4576,52 @@ int ObRawExprUtils::get_exec_param_expr(ObRawExprFactory &expr_factory, | ||||
|   // we create a new one here | ||||
|   if (OB_SUCC(ret) && NULL == param_expr) { | ||||
|     ObExecParamRawExpr *exec_param = NULL; | ||||
|     if (OB_FAIL(expr_factory.create_raw_expr(T_QUESTIONMARK, exec_param))) { | ||||
|       LOG_WARN("failed to create raw expr", K(ret)); | ||||
|     } else if (OB_ISNULL(exec_param)) { | ||||
|       ret = OB_ERR_UNEXPECTED; | ||||
|       LOG_WARN("exec param is null", K(ret), K(exec_param)); | ||||
|     if (OB_FAIL(ObRawExprUtils::create_new_exec_param(expr_factory, | ||||
|                                                       outer_val_expr, | ||||
|                                                       exec_param, | ||||
|                                                       false))) { | ||||
|       LOG_WARN("failed to create new exec param", K(ret)); | ||||
|     } else if (OB_FAIL(query_ref->add_exec_param_expr(exec_param))) { | ||||
|       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 { | ||||
|       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; | ||||
|     } | ||||
|   } | ||||
|   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, | ||||
|                                           ObRawExprFactory &expr_factory, | ||||
|                                           ObRawExpr *&expr, | ||||
|  | ||||
| @ -557,11 +557,10 @@ public: | ||||
|                                    ObRawExprFactory &expr_factory, | ||||
|                                    ObRawExpr *&expr, | ||||
|                                    bool is_onetime = false); | ||||
|  | ||||
|   static int create_exec_param_expr(ObQueryCtx *query_ctx, | ||||
|                                     ObRawExprFactory &expr_factory, | ||||
|                                     ObRawExpr *&src_expr, | ||||
|                                     std::pair<int64_t, ObRawExpr*> &init_expr); | ||||
|   static int create_new_exec_param(ObRawExprFactory &expr_factory, | ||||
|                                    ObRawExpr *ref_expr, | ||||
|                                    ObExecParamRawExpr *&exec_param, | ||||
|                                    bool is_onetime = false); | ||||
|   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, | ||||
|                              ObRawExprFactory &expr_factory, | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 jingtaoye35
					jingtaoye35