Bugfix for ObDecimalIntType

This commit is contained in:
obdev 2024-02-07 10:43:37 +00:00 committed by ob-robot
parent 7fc78f5b9d
commit b414155cd5
11 changed files with 258 additions and 83 deletions

View File

@ -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<ObIArray<ObRawExpr *> &>(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<ObRawExpr *> &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<ObConstRawExpr *>(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<ObRawExpr *> &raw_exprs)
rt_expr->args_[i] = get_rt_expr(*child_expr);
}
}
if (is_dyn_qm) {
int64_t param_idx = 0;
ret = static_cast<ObConstRawExpr *>(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<ObRawExpr *> &raw_e
ObConstRawExpr *c_expr = static_cast<ObConstRawExpr*>(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<int32_t>(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<ObRawExpr *> &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<ObRawExpr *> &raw_e
}
}
}
if (OB_SUCC(ret)) {
rt_expr->extra_ = static_cast<int64_t>(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<ObRawExpr *> &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<ObConstRawExpr *>(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<ObConstRawExpr *>(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<ObRawExpr *> &par
// datum_param_store中存放的信息,
// 当前使用场景是在ObExprValuesOp中进行动态cast时,
// 可以通过该下标最终获取参数化后原始参数值的类型;
rt_expr->extra_ = param_idx;
if (param_exprs.at(i)->is_const_expr()
&& static_cast<const ObConstRawExpr *>(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<ObRawExpr *> &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<const ObConstRawExpr *>(all_exprs.at(i))->is_dynamic_eval_questionmark()) {
ObRawExpr *gen_questionmark = all_exprs.at(i);
int64_t param_idx = 0;
ret = static_cast<ObConstRawExpr *>(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

View File

@ -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<ObRawExpr *> &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<ObRawExpr *, common::ObIAllocator> gen_questionmarks_;
};
} // end namespace sql

View File

@ -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

View File

@ -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 &param_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 &param_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 &param_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;
}

View File

@ -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<ObJsonDecimal*> (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

View File

@ -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<ObUserVarIdentRawExpr *> &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);
}

View File

@ -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));

View File

@ -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<const ObSysFunRawExpr&>(expr));
} else if (T_QUESTIONMARK == expr.get_expr_type()) {
bool_ret = true;
const ObConstRawExpr *c_expr = static_cast<const ObConstRawExpr *>(&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<const ObConstRawExpr &>(expr));
}
} else if (T_FUN_SYS_RAND == get_expr_type() ||
T_FUN_SYS_RANDOM == get_expr_type() ||
T_FUN_SYS_GUID == get_expr_type() ||

View File

@ -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<ParamExprPair, 3, common::ModulePageAllocator, true> 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<ObRawExprFactory> ObExprResolveContext;

View File

@ -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

View File

@ -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