From a084a7ae388924f301ed79748f6f505ac813cd5a Mon Sep 17 00:00:00 2001 From: Zach41 Date: Thu, 7 Dec 2023 11:12:43 +0000 Subject: [PATCH] Bugfix for dynamic evaluated questionmark --- .../ob_static_engine_expr_cg.cpp | 49 ++++++++++--------- .../code_generator/ob_static_engine_expr_cg.h | 1 + src/sql/engine/expr/ob_datum_decint_cast.h | 7 ++- .../resolver/expr/ob_raw_expr_deduce_type.cpp | 18 +++++-- 4 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/sql/code_generator/ob_static_engine_expr_cg.cpp b/src/sql/code_generator/ob_static_engine_expr_cg.cpp index 26c9843a5..cf5f518a9 100644 --- a/src/sql/code_generator/ob_static_engine_expr_cg.cpp +++ b/src/sql/code_generator/ob_static_engine_expr_cg.cpp @@ -309,9 +309,7 @@ int ObStaticEngineExprCG::cg_expr_basic(const ObIArray &raw_exprs) // do nothing. } else { // init arg_cnt_ - bool is_dyn_qm = (raw_expr->is_static_const_expr() - && raw_expr->get_expr_type() == T_QUESTIONMARK - && static_cast(raw_expr)->is_dynamic_eval_questionmark()); + bool is_dyn_qm = is_dynamic_eval_qm(*raw_expr); rt_expr->arg_cnt_ = raw_expr->get_param_count(); if (is_dyn_qm) { rt_expr->arg_cnt_ = 1; @@ -456,19 +454,15 @@ int ObStaticEngineExprCG::cg_expr_by_operator(const ObIArray &raw_e &eval_assign_question_mark_func: &eval_question_mark_func; } - } else if (T_QUESTIONMARK == rt_expr->type_ && raw_expr->is_static_const_expr() - && static_cast(raw_expr)->is_dynamic_eval_questionmark()) { + } else if (is_dynamic_eval_qm(*raw_expr)) { ObConstRawExpr *c_expr = static_cast(raw_expr); int64_t param_idx = 0; OZ(c_expr->get_value().get_unknown(param_idx)); - QuestionmarkDynEvalInfo dyn_info; if (OB_SUCC(ret)) { - dyn_info.param_idx_ = static_cast(param_idx); + rt_expr->extra_ = param_idx; if (c_expr->get_orig_qm_type().is_decimal_int() && ob_is_number_tc(rt_expr->datum_meta_.type_)) { const ObExprResType &orig_type = c_expr->get_orig_qm_type(); rt_expr->eval_func_ = eval_questionmark_decint2nmb; - dyn_info.in_scale_ = orig_type.get_accuracy().get_scale(); - dyn_info.in_precision_ = orig_type.get_accuracy().get_precision(); } else if (c_expr->get_orig_qm_type().is_number() && ob_is_decimal_int(rt_expr->datum_meta_.type_)) { ObCastMode cm = c_expr->get_result_type().get_cast_mode(); if ((cm & CM_CONST_TO_DECIMAL_INT_EQ) != 0) { @@ -480,8 +474,6 @@ int ObStaticEngineExprCG::cg_expr_by_operator(const ObIArray &raw_e } else if (c_expr->get_orig_qm_type().is_decimal_int() && ob_is_decimal_int(rt_expr->datum_meta_.type_)) { const ObExprResType &orig_type = c_expr->get_orig_qm_type(); ObCastMode cm = c_expr->get_result_type().get_cast_mode(); - dyn_info.in_precision_ = orig_type.get_accuracy().get_precision(); - dyn_info.in_scale_ = orig_type.get_accuracy().get_scale(); if ((cm & CM_CONST_TO_DECIMAL_INT_EQ) != 0) { rt_expr->eval_func_ = eval_questionmark_decint2decint_eqcast; } else if (OB_UNLIKELY(CM_IS_CONST_TO_DECIMAL_INT(cm))) { @@ -492,9 +484,6 @@ int ObStaticEngineExprCG::cg_expr_by_operator(const ObIArray &raw_e } } } - if (OB_SUCC(ret)) { - rt_expr->extra_ = static_cast(dyn_info); - } } else if (!IS_EXPR_OP(rt_expr->type_) || IS_AGGR_FUN(rt_expr->type_)) { // do nothing } else if (OB_FAIL(expr_cg_impl.generate_expr_operator(*raw_expr, expr_op_fetcher))) { @@ -606,9 +595,7 @@ int ObStaticEngineExprCG::classify_exprs(const ObIArray &raw_exprs, int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < raw_exprs.count(); i++) { ObItemType type = raw_exprs.at(i)->get_expr_type(); - bool is_dyn_qm = raw_exprs.at(i)->is_static_const_expr() - && raw_exprs.at(i)->get_expr_type() == T_QUESTIONMARK - && static_cast(raw_exprs.at(i))->is_dynamic_eval_questionmark(); + bool is_dyn_qm = is_dynamic_eval_qm(*raw_exprs.at(i)); if (T_QUESTIONMARK == type && !rt_question_mark_eval_ && !raw_exprs.at(i)->has_flag(IS_TABLE_ASSIGN) && !is_dyn_qm) { if (raw_exprs.at(i)->has_flag(IS_DYNAMIC_PARAM)) { @@ -708,8 +695,7 @@ int ObStaticEngineExprCG::cg_param_frame_layout(const ObIArray &par // datum_param_store中存放的信息, // 当前使用场景是在ObExprValuesOp中进行动态cast时, // 可以通过该下标最终获取参数化后原始参数值的类型; - if (param_exprs.at(i)->is_const_expr() - && static_cast(param_exprs.at(i))->is_dynamic_eval_questionmark()) { + if (is_dynamic_eval_qm(*param_exprs.at(i))) { // already set in `cg_expr_by_operator` } else { rt_expr->extra_ = param_idx; @@ -1605,15 +1591,21 @@ int ObStaticEngineExprCG::gen_expr_with_row_desc(const ObRawExpr *expr, ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allocate memory for temp expr", K(ret)); } + CK(OB_NOT_NULL(expr)); if (OB_SUCC(ret)) { LOG_TRACE("generate temp expr", K(*expr), K(row_desc)); + int64_t param_cnt = + (session->get_cur_exec_ctx() != NULL + && session->get_cur_exec_ctx()->get_physical_plan_ctx() != NULL) ? + session->get_cur_exec_ctx()->get_physical_plan_ctx()->get_param_store().count() : + 0; temp_expr = new(buf)ObTempExpr(allocator); ObStaticEngineExprCG expr_cg(allocator, session, schema_guard, 0, - 0, + param_cnt, GET_MIN_CLUSTER_VERSION()); // ? expr_cg.set_rt_question_mark_eval(true); expr_cg.set_need_flatten_gen_col(false); @@ -1851,7 +1843,9 @@ int ObStaticEngineExprCG::compute_max_batch_size(const ObRawExpr *raw_expr) int ObStaticEngineExprCG::generate_extra_questionmarks(ObRawExprUniqueSet &flattened_raw_exprs) { int ret = OB_SUCCESS; - if (OB_FAIL(gen_questionmarks_.prepare_allocate(param_cnt_))) { + if (OB_UNLIKELY(param_cnt_ <= 0)) { + // do nothing + } else if (OB_FAIL(gen_questionmarks_.prepare_allocate(param_cnt_))) { LOG_WARN("prepare allocate elements failed", K(ret)); } else { for (int i = 0; i < param_cnt_; i++) { @@ -1863,11 +1857,10 @@ int ObStaticEngineExprCG::generate_extra_questionmarks(ObRawExprUniqueSet &flatt if (OB_ISNULL(all_exprs.at(i))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null raw expr", K(ret), K(i)); - } else if (all_exprs.at(i)->is_static_const_expr() - && all_exprs.at(i)->get_expr_type() == T_QUESTIONMARK - && static_cast(all_exprs.at(i))->is_dynamic_eval_questionmark()) { + } else if (is_dynamic_eval_qm(*all_exprs.at(i))) { ObRawExpr *gen_questionmark = all_exprs.at(i); int64_t param_idx = 0; + ObExprResType orig_qm_type = static_cast(all_exprs.at(i))->get_orig_qm_type(); ret = static_cast(all_exprs.at(i))->get_value().get_unknown(param_idx); if (OB_FAIL(ret)) { LOG_WARN("get param index failed", K(ret)); @@ -1876,6 +1869,7 @@ int ObStaticEngineExprCG::generate_extra_questionmarks(ObRawExprUniqueSet &flatt } else if (OB_UNLIKELY(param_idx >= param_cnt_)) { LOG_WARN("unexpected param idx", K(ret), K(param_idx), K(param_cnt_)); } else { + gen_questionmark->set_result_type(orig_qm_type); gen_questionmarks_.at(param_idx) = gen_questionmark; } } @@ -1892,5 +1886,12 @@ int ObStaticEngineExprCG::generate_extra_questionmarks(ObRawExprUniqueSet &flatt return ret; } +bool ObStaticEngineExprCG::is_dynamic_eval_qm(const ObRawExpr &raw_expr) const +{ + return raw_expr.is_static_const_expr() && raw_expr.get_expr_type() == T_QUESTIONMARK + && static_cast(raw_expr).is_dynamic_eval_questionmark() + && param_cnt_ > 0; +} + } // end namespace sql } // end namespace oceanbase diff --git a/src/sql/code_generator/ob_static_engine_expr_cg.h b/src/sql/code_generator/ob_static_engine_expr_cg.h index 1dbd15c6f..af68c0f4f 100644 --- a/src/sql/code_generator/ob_static_engine_expr_cg.h +++ b/src/sql/code_generator/ob_static_engine_expr_cg.h @@ -410,6 +410,7 @@ private: private: int generate_extra_questionmarks(ObRawExprUniqueSet &flattened_raw_exprs); + bool is_dynamic_eval_qm(const ObRawExpr &raw_expr) const; private: // disallow copy DISALLOW_COPY_AND_ASSIGN(ObStaticEngineExprCG); diff --git a/src/sql/engine/expr/ob_datum_decint_cast.h b/src/sql/engine/expr/ob_datum_decint_cast.h index 09a85656a..46b667e0f 100644 --- a/src/sql/engine/expr/ob_datum_decint_cast.h +++ b/src/sql/engine/expr/ob_datum_decint_cast.h @@ -1225,10 +1225,10 @@ int eval_questionmark_decint2nmb(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &ex int ret = OB_SUCCESS; // child is questionmark, do not need evaluation. const ObDatum &child = expr.args_[0]->locate_expr_datum(ctx); - QuestionmarkDynEvalInfo dyn_info(expr.extra_); + ObScale in_scale = expr.args_[0]->datum_meta_.scale_; ObNumStackOnceAlloc tmp_alloc; number::ObNumber out_nmb; - if (OB_FAIL(wide::to_number(child.get_decimal_int(), child.get_int_bytes(), dyn_info.in_scale_, + if (OB_FAIL(wide::to_number(child.get_decimal_int(), child.get_int_bytes(), in_scale, tmp_alloc, out_nmb))) { LOG_WARN("to_number failed", K(ret)); } else { @@ -1266,8 +1266,7 @@ static int _eval_questionmark_decint2decint(const ObExpr &expr, ObEvalCtx &ctx, int ret = OB_SUCCESS; ObScale out_scale = expr.datum_meta_.scale_; ObPrecision out_prec = expr.datum_meta_.precision_; - QuestionmarkDynEvalInfo dyn_info(expr.extra_); - ObScale in_scale = dyn_info.in_scale_; + ObScale in_scale = expr.args_[0]->datum_meta_.scale_; ObDecimalIntBuilder res_val; const ObDatum &child = expr.args_[0]->locate_expr_datum(ctx); if (OB_FAIL(ObDatumCast::common_scale_decimalint(child.get_decimal_int(), child.get_int_bytes(), diff --git a/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp b/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp index f01e075f9..6d8363430 100644 --- a/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp @@ -3772,7 +3772,7 @@ int ObRawExprDeduceType::try_replace_casts_with_questionmarks_ora(ObRawExpr *row return ret; } -int ObRawExprDeduceType::try_replace_cast_with_questionmark_ora(ObRawExpr &parent, ObRawExpr *cast_expr, int param_idx) +int ObRawExprDeduceType::try_replace_cast_with_questionmark_ora(ObRawExpr &parent, ObRawExpr *cast_expr, int child_idx) { int ret = OB_SUCCESS; if (OB_ISNULL(cast_expr)) { @@ -3791,14 +3791,24 @@ int ObRawExprDeduceType::try_replace_cast_with_questionmark_ora(ObRawExpr &paren bool is_nmb2decint = param_expr->get_result_type().is_number() && cast_expr->get_result_type().is_decimal_int(); bool is_decint2decint = param_expr->get_result_type().is_decimal_int() && cast_expr->get_result_type().is_decimal_int(); if (param_expr->is_static_const_expr() && param_expr->get_expr_type() == T_QUESTIONMARK + && !static_cast(param_expr)->is_dynamic_eval_questionmark() // already replaced && (is_decint2nmb || is_nmb2decint || is_decint2decint)) { + ObConstRawExpr *c_expr = static_cast(param_expr); ObExprResType res_type = cast_expr->get_result_type(); res_type.add_cast_mode(cast_expr->get_extra()); - ret = static_cast(param_expr)->set_dynamic_eval_questionmark(res_type); - if (OB_FAIL(ret)) { + int64_t param_idx = 0; + if (OB_ISNULL(expr_factory_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null raw expr", K(ret)); + } else if (OB_FAIL(c_expr->get_value().get_unknown(param_idx))) { + LOG_WARN("get param idx failed", K(ret)); + } else if (OB_FAIL(ObRawExprUtils::create_param_expr(*expr_factory_, param_idx, param_expr))) { + // create new param store to avoid unexpected problem + LOG_WARN("create param expr failed", K(ret)); + } else if (OB_FAIL(static_cast(param_expr)->set_dynamic_eval_questionmark(res_type))){ LOG_WARN("set dynamic eval question mark failed", K(ret)); } else { - parent.get_param_expr(param_idx) = param_expr; + parent.get_param_expr(child_idx) = param_expr; } } LOG_DEBUG("replace cast with questionmark", K(*cast_expr), K(is_decint2nmb), K(is_nmb2decint),