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

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