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 155a7c1840..26c9843a5c 100644 --- a/src/sql/code_generator/ob_static_engine_expr_cg.cpp +++ b/src/sql/code_generator/ob_static_engine_expr_cg.cpp @@ -19,6 +19,7 @@ #include "sql/engine/expr/ob_expr_util.h" #include "sql/engine/expr/ob_expr_extra_info_factory.h" #include "sql/engine/expr/ob_expr_lob_utils.h" +#include "sql/engine/expr/ob_datum_cast.h" namespace oceanbase { @@ -61,6 +62,8 @@ int ObStaticEngineExprCG::generate(const ObRawExprUniqueSet &all_raw_exprs, // do nothing } else if (OB_FAIL(flattened_raw_exprs.flatten_and_add_raw_exprs(all_raw_exprs))) { LOG_WARN("failed to flatten raw exprs", K(ret)); + } else if (OB_FAIL(generate_extra_questionmarks(flattened_raw_exprs))) { + LOG_WARN("generate extra question marks failed", K(ret)); } else if (OB_FAIL(divide_probably_local_exprs( const_cast &>(flattened_raw_exprs.get_expr_array())))) { LOG_WARN("divided probably local exprs failed", K(ret)); @@ -81,6 +84,8 @@ int ObStaticEngineExprCG::generate(ObRawExpr *expr, int ret = OB_SUCCESS; if (OB_FAIL(flattened_raw_exprs.flatten_temp_expr(expr))) { LOG_WARN("failed to flatten raw exprs", K(ret)); + } else if (OB_FAIL(generate_extra_questionmarks(flattened_raw_exprs))) { + LOG_WARN("generate extra questionmarks failed", K(ret)); } else if (OB_FAIL(construct_exprs(flattened_raw_exprs.get_expr_array(), expr_info.rt_exprs_))) { LOG_WARN("failed to construct rt exprs", K(ret)); @@ -304,7 +309,13 @@ 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()); rt_expr->arg_cnt_ = raw_expr->get_param_count(); + if (is_dyn_qm) { + rt_expr->arg_cnt_ = 1; + } // init args_; if (rt_expr->arg_cnt_ > 0) { int64_t alloc_size = rt_expr->arg_cnt_ * sizeof(ObExpr *); @@ -328,6 +339,19 @@ int ObStaticEngineExprCG::cg_expr_basic(const ObIArray &raw_exprs) rt_expr->args_[i] = get_rt_expr(*child_expr); } } + if (is_dyn_qm) { + int64_t param_idx = 0; + ret = static_cast(raw_expr)->get_value().get_unknown(param_idx); + LOG_DEBUG("generate rt expr basic", K(param_idx), K(*gen_questionmarks_.at(param_idx))); + if (OB_FAIL(ret)) { + LOG_WARN("get param idx failed", K(ret)); + } else if (OB_ISNULL(gen_questionmarks_.at(param_idx))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null questionmark", K(ret), K(param_idx)); + } else { + rt_expr->args_[0] = get_rt_expr(*gen_questionmarks_.at(param_idx)); + } + } } } } @@ -437,11 +461,14 @@ int ObStaticEngineExprCG::cg_expr_by_operator(const ObIArray &raw_e 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)) { - rt_expr->extra_ = param_idx; - // rt_expr->eval_func_ = dynamic_eval_questionmark; + dyn_info.param_idx_ = static_cast(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) { @@ -451,7 +478,10 @@ int ObStaticEngineExprCG::cg_expr_by_operator(const ObIArray &raw_e LOG_WARN("unpexected cast mode", K(ret), K(cm)); } } 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))) { @@ -462,6 +492,9 @@ 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))) { @@ -573,11 +606,11 @@ 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_dynamic_eval_questionamrk = - raw_exprs.at(i)->is_static_const_expr() - && static_cast(raw_exprs.at(i))->is_dynamic_eval_questionmark(); + 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(); if (T_QUESTIONMARK == type && !rt_question_mark_eval_ - && !raw_exprs.at(i)->has_flag(IS_TABLE_ASSIGN) && !is_dynamic_eval_questionamrk) { + && !raw_exprs.at(i)->has_flag(IS_TABLE_ASSIGN) && !is_dyn_qm) { if (raw_exprs.at(i)->has_flag(IS_DYNAMIC_PARAM)) { // if questionmark is dynamic evaluated, e.g. decint->nmb, use dynamic_param_frame as its memory if (dynamic_param_exprs.push_back(raw_exprs.at(i))) { @@ -675,7 +708,12 @@ int ObStaticEngineExprCG::cg_param_frame_layout(const ObIArray &par // datum_param_store中存放的信息, // 当前使用场景是在ObExprValuesOp中进行动态cast时, // 可以通过该下标最终获取参数化后原始参数值的类型; - rt_expr->extra_ = param_idx; + if (param_exprs.at(i)->is_const_expr() + && static_cast(param_exprs.at(i))->is_dynamic_eval_questionmark()) { + // already set in `cg_expr_by_operator` + } else { + rt_expr->extra_ = param_idx; + } } } } @@ -1788,5 +1826,71 @@ int ObStaticEngineExprCG::compute_max_batch_size(const ObRawExpr *raw_expr) (1 + sizeof(ObDatum) + reserve_data_consume(result_type.get_type(), result_type.get_precision())); } +// this is used for dynamic evaluated questionmark exprs +// consider following query in oracle mode: +// ```SQL +// create table t (a int); +// select * from t where a in (1, 2); # item count in row maybe very large! +// ``` +// numeric constants are parsed as ObDecimalIntType, +// thus execution sql will be like: `select * from t where a in (cast(:0 as number), cast(:1 as number))` +// in order to reduce sql optimization cost , we replace cast with question marks: +// `select * from t where a in (?, ?)` and evaluated questionmark exprs during runtime. +// To summarize, we get rt_exprs which: +// 1. expr_type equal to T_QUESTIONMARK +// 2. eval_func_ not empty +// In order to avoid unexpected situations, we create questionmark rt_exprs for original question marks (`1` & `2`) +// final in expr will be like : +// in_expr +// |- column_ref +// |- op_row +// |- questionmark +// |- questionmark(:0) +// |- questionmark +// |- questionmark(:1) +int ObStaticEngineExprCG::generate_extra_questionmarks(ObRawExprUniqueSet &flattened_raw_exprs) +{ + int ret = OB_SUCCESS; + 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++) { + gen_questionmarks_.at(i) = nullptr; + } + ObRawExprFactory expr_factory(allocator_); + const ObIArray &all_exprs = flattened_raw_exprs.get_expr_array(); + for (int i = 0; OB_SUCC(ret) && i < all_exprs.count(); i++) { + 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()) { + ObRawExpr *gen_questionmark = all_exprs.at(i); + int64_t param_idx = 0; + 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)); + } else if (OB_FAIL(ObRawExprUtils::create_param_expr(expr_factory, param_idx, gen_questionmark))) { + LOG_WARN("create param expr failed", K(ret)); + } else if (OB_UNLIKELY(param_idx >= param_cnt_)) { + LOG_WARN("unexpected param idx", K(ret), K(param_idx), K(param_cnt_)); + } else { + gen_questionmarks_.at(param_idx) = gen_questionmark; + } + } + } + LOG_DEBUG("extra question marks", K(gen_questionmarks_)); + for (int i = 0; OB_SUCC(ret) && i < gen_questionmarks_.count(); i++) { + if (OB_NOT_NULL(gen_questionmarks_.at(i))) { + if (OB_FAIL(flattened_raw_exprs.append(gen_questionmarks_.at(i)))) { + LOG_WARN("append raw expr failed", K(ret)); + } + } + } + } + return ret; +} + } // 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 30f71b00df..1dbd15c6f4 100644 --- a/src/sql/code_generator/ob_static_engine_expr_cg.h +++ b/src/sql/code_generator/ob_static_engine_expr_cg.h @@ -16,6 +16,7 @@ #include "sql/engine/expr/ob_expr.h" #include "sql/engine/expr/ob_expr_frame_info.h" #include "share/ob_cluster_version.h" +#include "lib/container/ob_fixed_array.h" namespace oceanbase { @@ -103,7 +104,8 @@ public: batch_size_(0), rt_question_mark_eval_(false), need_flatten_gen_col_(true), - cur_cluster_version_(cur_cluster_version) + cur_cluster_version_(cur_cluster_version), + gen_questionmarks_(allocator, param_cnt) { } virtual ~ObStaticEngineExprCG() {} @@ -406,6 +408,8 @@ private: int divide_probably_local_exprs(common::ObIArray &exprs); +private: + int generate_extra_questionmarks(ObRawExprUniqueSet &flattened_raw_exprs); private: // disallow copy DISALLOW_COPY_AND_ASSIGN(ObStaticEngineExprCG); @@ -433,6 +437,7 @@ private: //is code generate temp expr witch used in table location bool need_flatten_gen_col_; uint64_t cur_cluster_version_; + common::ObFixedArray gen_questionmarks_; }; } // end namespace sql diff --git a/src/sql/engine/expr/ob_datum_cast.h b/src/sql/engine/expr/ob_datum_cast.h index b6d90fe998..6552bac6f3 100644 --- a/src/sql/engine/expr/ob_datum_cast.h +++ b/src/sql/engine/expr/ob_datum_cast.h @@ -308,6 +308,26 @@ private: static batch_func_ explicit_batch_funcs_[ObMaxTC][ObMaxTC]; }; +struct QuestionmarkDynEvalInfo +{ + union + { + struct + { + int16_t in_scale_; + int16_t in_precision_; + int32_t param_idx_; + }; + int64_t extra_; + }; + QuestionmarkDynEvalInfo() : extra_(0){}; + QuestionmarkDynEvalInfo(int64_t extra): extra_(extra) {} + explicit operator int64_t() + { + return extra_; + } +}; + } // namespace sql } // namespace oceanbase diff --git a/src/sql/engine/expr/ob_datum_decint_cast.h b/src/sql/engine/expr/ob_datum_decint_cast.h index 0f05199991..09a85656af 100644 --- a/src/sql/engine/expr/ob_datum_decint_cast.h +++ b/src/sql/engine/expr/ob_datum_decint_cast.h @@ -1223,29 +1223,16 @@ REG_SER_FUNC_ARRAY(OB_SFA_DECIMAL_INT_CAST_EXPR_EVAL_BATCH, g_decimalint_cast_ba int eval_questionmark_decint2nmb(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum) { int ret = OB_SUCCESS; - if (OB_ISNULL(ctx.exec_ctx_.get_physical_plan_ctx())) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("NULL plan ctx", K(ret)); + // child is questionmark, do not need evaluation. + const ObDatum &child = expr.args_[0]->locate_expr_datum(ctx); + QuestionmarkDynEvalInfo dyn_info(expr.extra_); + 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_, + tmp_alloc, out_nmb))) { + LOG_WARN("to_number failed", K(ret)); } else { - const ParamStore ¶m_store = ctx.exec_ctx_.get_physical_plan_ctx()->get_param_store(); - if (expr.extra_ >= param_store.count()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid param store idx", K(ret), K(expr), K(param_store.count())); - } else { - const ObObj &v = param_store.at(expr.extra_); - ObNumStackOnceAlloc tmp_alloc; - ObIAllocator &eval_allocator = ctx.exec_ctx_.get_eval_res_allocator(); - number::ObNumber out_nmb; - if (v.get_type() != ObDecimalIntType) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid decimal int", K(ret), K(v)); - } else if (OB_FAIL(wide::to_number(v.get_decimal_int(), v.get_int_bytes(), v.get_scale(), - tmp_alloc, out_nmb))) { - LOG_WARN("to_number failed", K(ret)); - } else { - expr_datum.set_number(out_nmb); - } - } + expr_datum.set_number(out_nmb); } return ret; } @@ -1254,34 +1241,18 @@ static int _eval_questionmark_nmb2decint(const ObExpr &expr, ObEvalCtx &ctx, ObD const ObCastMode cm) { int ret = OB_SUCCESS; - number::ObNumber in_nmb; + // child is questionmark, do not need evaluation. + const ObDatum &child = expr.args_[0]->locate_expr_datum(ctx); ObDecimalIntBuilder tmp_alloc, res_val; - ObDecimalInt *decint = nullptr; - int32_t int_bytes = 0; + number::ObNumber in_nmb(child.get_number()); + ObScale in_scale = in_nmb.get_scale(); ObPrecision out_prec = expr.datum_meta_.precision_; ObScale out_scale = expr.datum_meta_.scale_; - ObScale in_scale = 0; - if (OB_ISNULL(ctx.exec_ctx_.get_physical_plan_ctx())) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("NULL plan ctx", K(ret)); - } else { - const ParamStore ¶m_store = ctx.exec_ctx_.get_physical_plan_ctx()->get_param_store(); - if (expr.extra_ >= param_store.count()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid param store idx", K(ret), K(expr), K(param_store.count())); - } else { - const ObObj &v = param_store.at(expr.extra_); - if (OB_FAIL(v.get_number(in_nmb))) { - LOG_WARN("get number from object failed", K(ret)); - } - } - } - if (OB_FAIL(ret)) { - } else if (FALSE_IT(in_scale = in_nmb.get_scale())) { - } else if (OB_FAIL(wide::from_number(in_nmb, tmp_alloc, in_scale, decint, int_bytes))) { - LOG_WARN("from number failed", K(ret), K(in_nmb)); - } else if (OB_FAIL(scale_const_decimalint_expr(decint, int_bytes, in_scale, out_scale, out_prec, - cm, res_val))) { + ObDecimalInt *decint = nullptr; + int32_t int_bytes = 0; + if (OB_FAIL(wide::from_number(in_nmb, tmp_alloc, in_scale, decint, int_bytes))) { + LOG_WARN("from number failed", K(ret)); + } else if (OB_FAIL(scale_const_decimalint_expr(decint, int_bytes, in_scale, out_scale, out_prec, cm, res_val))) { LOG_WARN("scale const decimal int failed", K(ret)); } else { expr_datum.set_decimal_int(res_val.get_decimal_int(), res_val.get_int_bytes()); @@ -1295,25 +1266,15 @@ 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_; ObDecimalIntBuilder res_val; - if (OB_ISNULL(ctx.exec_ctx_.get_physical_plan_ctx())) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("NULL plan ctx", K(ret)); + 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(), + in_scale, out_scale, out_prec, cm, res_val))) { + LOG_WARN("common scale decimal int failed", K(ret)); } else { - const ParamStore ¶m_store = ctx.exec_ctx_.get_physical_plan_ctx()->get_param_store(); - if (expr.extra_ >= param_store.count()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid param store idx", K(ret), K(expr), K(param_store.count())); - } else { - const ObObj &v = param_store.at(expr.extra_); - if (OB_FAIL(ObDatumCast::common_scale_decimalint(v.get_decimal_int(), v.get_int_bytes(), - v.get_scale(), out_scale, out_prec, cm, - res_val))) { - LOG_WARN("scale decimal int failed", K(ret)); - } else { - expr_datum.set_decimal_int(res_val.get_decimal_int(), res_val.get_int_bytes()); - } - } + expr_datum.set_decimal_int(res_val.get_decimal_int(), res_val.get_int_bytes()); } return ret; } diff --git a/src/sql/engine/expr/ob_expr_json_exists.cpp b/src/sql/engine/expr/ob_expr_json_exists.cpp index 8960c12f11..db8d63cd59 100644 --- a/src/sql/engine/expr/ob_expr_json_exists.cpp +++ b/src/sql/engine/expr/ob_expr_json_exists.cpp @@ -184,6 +184,7 @@ int ObExprJsonExists::get_var_data(const ObExpr &expr, ObEvalCtx &ctx, common::O ObExpr *json_arg = expr.args_[index]; ObObjType val_type = json_arg->datum_meta_.type_; ObCollationType cs_type = json_arg->datum_meta_.cs_type_; + ObScale dec_scale = json_arg->datum_meta_.scale_; if (OB_UNLIKELY(OB_FAIL(json_arg->eval(ctx, json_datum)))) { LOG_WARN("eval json arg failed", K(ret)); @@ -273,15 +274,24 @@ int ObExprJsonExists::get_var_data(const ObExpr &expr, ObEvalCtx &ctx, common::O j_base = tmp_ans; } } - } else if (ObNumberType <= val_type && val_type <= ObUNumberType) { + } else if ((ObNumberType <= val_type && val_type <= ObUNumberType) || (val_type == ObDecimalIntType)) { // decimal ObJsonDecimal* tmp_ans = static_cast (allocator.alloc(sizeof(ObJsonDecimal))); if (OB_ISNULL(tmp_ans)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate row buffer failed at ObJsonDecimal", K(ret)); - } else { + } else if (val_type != ObDecimalIntType){ tmp_ans = new (tmp_ans) ObJsonDecimal(json_datum->get_number()); j_base = tmp_ans; + } else { + ObNumber tmp_nmb; + if (OB_FAIL(wide::to_number(json_datum->get_decimal_int(), json_datum->get_int_bytes(), + dec_scale, allocator, tmp_nmb))) { + LOG_WARN("to number faile", K(ret)); + } else { + tmp_ans = new (tmp_ans) ObJsonDecimal(tmp_nmb); + j_base = tmp_ans; + } } } else if (val_type == ObDateTimeType || val_type == ObDateType || val_type == ObTimeType) { // datetime diff --git a/src/sql/resolver/dml/ob_dml_resolver.cpp b/src/sql/resolver/dml/ob_dml_resolver.cpp index 5f47f225fe..1d60abd4cd 100755 --- a/src/sql/resolver/dml/ob_dml_resolver.cpp +++ b/src/sql/resolver/dml/ob_dml_resolver.cpp @@ -1422,6 +1422,7 @@ int ObDMLResolver::resolve_sql_expr(const ParseNode &node, ObRawExpr *&expr, ctx.is_for_dbms_sql_ = params_.is_dbms_sql_; ctx.view_ref_id_ = view_ref_id_; ctx.is_variable_allowed_ = !(is_mysql_mode() && params_.is_from_create_view_); + ctx.is_expanding_view_ = params_.is_expanding_view_; ObRawExprResolverImpl expr_resolver(ctx); ObIArray &user_var_exprs = get_stmt()->get_user_vars(); bool is_multi_stmt = session_info_->get_cur_exec_ctx() != NULL && @@ -5027,6 +5028,7 @@ int ObDMLResolver::expand_view(TableItem &view_item) } } if (OB_SUCC(ret)) { + params_.is_expanding_view_ = true; ObViewTableResolver view_resolver(params_, get_view_db_name(), get_view_name()); view_resolver.set_current_level(current_level_); view_resolver.set_current_view_level(current_view_level_ + 1); @@ -5036,6 +5038,7 @@ int ObDMLResolver::expand_view(TableItem &view_item) if (OB_FAIL(do_expand_view(view_item, view_resolver))) { LOG_WARN("do expand view resolve failed", K(ret)); } + params_.is_expanding_view_ = false; if (!is_oracle_mode) { params_.schema_checker_->get_schema_guard()->set_session_id(org_session_id); } diff --git a/src/sql/resolver/dml/ob_select_resolver.cpp b/src/sql/resolver/dml/ob_select_resolver.cpp index fab535364c..2fb3967ea9 100644 --- a/src/sql/resolver/dml/ob_select_resolver.cpp +++ b/src/sql/resolver/dml/ob_select_resolver.cpp @@ -4332,6 +4332,7 @@ int ObSelectResolver::check_grouping_columns(ObSelectStmt &stmt, ObRawExpr *&exp ObStmtCompareContext questionmark_checker; questionmark_checker.reset(); questionmark_checker.override_const_compare_ = true; + questionmark_checker.ora_numeric_compare_ = true; if (OB_ISNULL(params_.query_ctx_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null pointer.", K(ret)); diff --git a/src/sql/resolver/expr/ob_raw_expr.cpp b/src/sql/resolver/expr/ob_raw_expr.cpp index 1ed8572003..9f38ab373a 100644 --- a/src/sql/resolver/expr/ob_raw_expr.cpp +++ b/src/sql/resolver/expr/ob_raw_expr.cpp @@ -1010,7 +1010,9 @@ bool ObConstRawExpr::inner_same_as( //what are you doing ? if (NULL != check_context) { if (expr.is_const_raw_expr()) { - if (T_QUESTIONMARK == expr.get_expr_type()) { + if (check_context->ora_numeric_compare_ && T_FUN_SYS_CAST == expr.get_expr_type() && lib::is_oracle_mode()) { + bool_ret = check_context->compare_ora_numeric_consts(*this, static_cast(expr)); + } else if (T_QUESTIONMARK == expr.get_expr_type()) { bool_ret = true; const ObConstRawExpr *c_expr = static_cast(&expr); int64_t param_idx = -1; @@ -1082,6 +1084,58 @@ bool ObExprEqualCheckContext::compare_const(const ObConstRawExpr &left, return result; } +bool ObExprEqualCheckContext::compare_ora_numeric_consts(const ObConstRawExpr &left, + const ObSysFunRawExpr &right) +{ + int &ret = err_code_; + bool result = false; + if (OB_LIKELY(lib::is_oracle_mode() && right.is_const_expr() && right.get_expr_type() == T_FUN_SYS_CAST)) { + ObCastMode cm = right.get_extra(); + const ObRawExpr *real_right = nullptr; + bool is_lossless = false; + if (CM_IS_IMPLICIT_CAST(cm) && !CM_IS_CONST_TO_DECIMAL_INT(cm)) { + if (OB_FAIL(ObOptimizerUtil::is_lossless_column_cast(&right, is_lossless))) { + LOG_WARN("check lossless cast failed", K(ret)); + } else if (is_lossless) { + real_right = right.get_param_expr(0); + if (OB_ISNULL(real_right)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid null param expr", K(ret)); + } else { + result = left.same_as(*real_right, this); + } + } + } + } + return result; +} + +bool ObExprEqualCheckContext::compare_ora_numeric_consts(const ObSysFunRawExpr &left, const ObConstRawExpr &right) +{ + int &ret = err_code_; + LOG_INFO("debug test"); + bool result = false; + if (OB_LIKELY(lib::is_oracle_mode() && left.get_expr_type()== T_FUN_SYS_CAST && left.is_const_expr())) { + ObCastMode cm = left.get_extra(); + const ObRawExpr *real_left = nullptr; + bool is_lossless = false; + if (CM_IS_IMPLICIT_CAST(cm) && !CM_IS_CONST_TO_DECIMAL_INT(cm)) { + if (OB_FAIL(ObOptimizerUtil::is_lossless_column_cast(&left, is_lossless))) { + LOG_WARN("check lossless cast failed", K(ret)); + } else if (is_lossless) { + real_left = left.get_param_expr(0); + if (OB_ISNULL(real_left)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid null param expr", K(ret)); + } else { + result = real_left->same_as(right, this); + } + } + } + } + return result; +} + int ObConstRawExpr::do_visit(ObRawExprVisitor &visitor) { return visitor.visit(*this); @@ -3721,6 +3775,10 @@ bool ObSysFunRawExpr::inner_same_as( { bool bool_ret = false; if (get_expr_type() != expr.get_expr_type()) { + if (check_context != NULL && check_context->ora_numeric_compare_ && expr.is_const_raw_expr() + && T_FUN_SYS_CAST == get_expr_type() && lib::is_oracle_mode()) { + bool_ret = check_context->compare_ora_numeric_consts(*this, static_cast(expr)); + } } else if (T_FUN_SYS_RAND == get_expr_type() || T_FUN_SYS_RANDOM == get_expr_type() || T_FUN_SYS_GUID == get_expr_type() || diff --git a/src/sql/resolver/expr/ob_raw_expr.h b/src/sql/resolver/expr/ob_raw_expr.h index c396a1b08b..a58764feef 100644 --- a/src/sql/resolver/expr/ob_raw_expr.h +++ b/src/sql/resolver/expr/ob_raw_expr.h @@ -1371,7 +1371,8 @@ struct ObExprEqualCheckContext err_code_(common::OB_SUCCESS), param_expr_(), need_check_deterministic_(false), - ignore_param_(false) + ignore_param_(false), + ora_numeric_compare_(false) { } ObExprEqualCheckContext(bool need_check_deterministic) : override_const_compare_(false), @@ -1383,7 +1384,8 @@ struct ObExprEqualCheckContext err_code_(common::OB_SUCCESS), param_expr_(), need_check_deterministic_(need_check_deterministic), - ignore_param_(false) + ignore_param_(false), + ora_numeric_compare_(false) { } virtual ~ObExprEqualCheckContext() {} struct ParamExprPair @@ -1419,6 +1421,9 @@ struct ObExprEqualCheckContext virtual bool compare_set_op_expr(const ObSetOpRawExpr& left, const ObSetOpRawExpr& right); + virtual bool compare_ora_numeric_consts(const ObConstRawExpr &left, const ObSysFunRawExpr &right); + + virtual bool compare_ora_numeric_consts(const ObSysFunRawExpr &right, const ObConstRawExpr &left); void reset() { override_const_compare_ = false; override_column_compare_ = false; @@ -1442,6 +1447,7 @@ struct ObExprEqualCheckContext common::ObSEArray param_expr_; bool need_check_deterministic_; bool ignore_param_; // only compare structure of expr + bool ora_numeric_compare_; }; struct ObExprParamCheckContext : ObExprEqualCheckContext @@ -1565,7 +1571,8 @@ struct ObResolveContext is_for_dbms_sql_(false), tg_timing_event_(TG_TIMING_EVENT_INVALID), view_ref_id_(OB_INVALID_ID), - is_variable_allowed_(true) + is_variable_allowed_(true), + is_expanding_view_(false) { } @@ -1611,6 +1618,7 @@ struct ObResolveContext TgTimingEvent tg_timing_event_; // for mysql trigger uint64_t view_ref_id_; bool is_variable_allowed_; + bool is_expanding_view_; }; typedef ObResolveContext ObExprResolveContext; diff --git a/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp b/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp index fd51b5f555..3222e1f72f 100644 --- a/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp @@ -162,10 +162,10 @@ int ObRawExprResolverImpl::try_negate_const(ObRawExpr *&expr, ObObj new_val; if (const_expr->get_value().is_decimal_int()) { ObDecimalInt *neg_dec = nullptr; - if (is_odd - && OB_FAIL(wide::negate(const_expr->get_value().get_decimal_int(), - const_expr->get_value().get_int_bytes(), neg_dec, - ctx_.expr_factory_.get_allocator()))) { + if (!is_odd) {// do nothing + } else if (OB_FAIL(wide::negate(const_expr->get_value().get_decimal_int(), + const_expr->get_value().get_int_bytes(), neg_dec, + ctx_.expr_factory_.get_allocator()))) { LOG_WARN("negate decimal int failed", K(ret)); } else { new_val.set_decimal_int(const_expr->get_value().get_int_bytes(), @@ -2522,6 +2522,9 @@ int ObRawExprResolverImpl::process_datatype_or_questionmark(const ParseNode &nod LOG_WARN("get sys variables failed", K(ret)); } else if (OB_FAIL(ObSQLUtils::check_enable_decimalint(session_info, enable_decimal_int))) { LOG_WARN("fail to check enable decimal int", K(ret)); + } else if (lib::is_oracle_mode() && ctx_.is_expanding_view_) { + // numeric constants should parsed with ObNumber in view expansion for oracle mode + enable_decimal_int = false; } if (OB_FAIL(ret)) { // do nothing diff --git a/src/sql/resolver/ob_resolver_define.h b/src/sql/resolver/ob_resolver_define.h index 4abdf26d15..91e3047954 100644 --- a/src/sql/resolver/ob_resolver_define.h +++ b/src/sql/resolver/ob_resolver_define.h @@ -347,7 +347,8 @@ struct ObResolverParams enable_res_map_(false), need_check_col_dup_(true), is_specified_col_name_(false), - is_in_sys_view_(false) + is_in_sys_view_(false), + is_expanding_view_(false) {} bool is_force_trace_log() { return force_trace_log_; } @@ -414,6 +415,7 @@ public: bool need_check_col_dup_; bool is_specified_col_name_;//mark if specify the column name in create view or create table as.. bool is_in_sys_view_; + bool is_expanding_view_; }; } // end namespace sql } // end namespace oceanbase