Fix row comparison wrong result of decimal int type

This commit is contained in:
hezuojiao
2024-01-19 02:42:37 +00:00
committed by ob-robot
parent e8bde18018
commit 658c51919f
20 changed files with 542 additions and 7 deletions

View File

@ -3101,6 +3101,20 @@ int ObSubQueryRelationalExpr::calc_result_typeN(ObExprResType &type,
ObExprResType tmp_res_type;
OZ(ObRelationalExprOperator::deduce_cmp_type(
*this, tmp_res_type, types[i], types[i + row_dimension_], type_ctx));
// For the multi-dimensional comparison of decimal int and varchar (for T_OP_SQ_LT and
// T_OP_SQ_LT), we set the calc type to number to avoid the correctness problem introduced
// by the loss of precision of one-sided cast.
if ((type_ == T_OP_SQ_LT || type_ == T_OP_SQ_GT) &&
ob_is_decimal_int(tmp_res_type.get_calc_meta().get_type())) {
ObExprResType &left = types[i];
ObExprResType &right = types[i + row_dimension_];
if ((ob_is_decimal_int_tc(left.get_type()) && ob_is_string_or_lob_type(right.get_type())) ||
(ob_is_string_or_lob_type(left.get_type()) && ob_is_decimal_int_tc(right.get_type()))) {
left.set_calc_type(ObNumberType);
right.set_calc_type(ObNumberType);
tmp_res_type.set_calc_type(ObNumberType);
}
}
OZ(type.get_row_calc_cmp_types().push_back(tmp_res_type.get_calc_meta()));
if (OB_SUCC(ret)) {
if (ob_is_string_type(tmp_res_type.get_calc_type())) {
@ -6541,11 +6555,21 @@ int ObRelationalExprOperator::row_cmp(
// locate first non-equal pair
for (; OB_SUCC(ret) && i < expr.inner_func_cnt_; i++) {
if (OB_FAIL(l_row[i]->eval(l_ctx, left))) {
LOG_WARN("failed to eval left in row cmp", K(ret));
if (OB_FAIL(try_get_inner_row_cmp_ret<true>(ret, first_nonequal_cmp_ret))) {
LOG_WARN("failed to eval left in row cmp", K(ret));
} else {
--i;
break;
}
} else if (left->is_null()) {
cnt_row_null = true;
} else if (OB_FAIL(r_row[i]->eval(r_ctx, right))) {
LOG_WARN("failed to eval right in row cmp", K(ret));
if (OB_FAIL(try_get_inner_row_cmp_ret<false>(ret, first_nonequal_cmp_ret))) {
LOG_WARN("failed to eval right in row cmp", K(ret));
} else {
--i;
break;
}
} else if (right->is_null()) {
cnt_row_null = true;
} else if (OB_FAIL(((DatumCmpFunc)expr.inner_functions_[i])(*left, *right, first_nonequal_cmp_ret))) {
@ -6580,6 +6604,20 @@ int ObRelationalExprOperator::row_cmp(
return ret;
}
template <bool IS_LEFT>
int ObRelationalExprOperator::try_get_inner_row_cmp_ret(const int ret_code, int &cmp_ret)
{
int ret = OB_SUCCESS;
if (ret_code == OB_ERR_MAX_VALUE) {
cmp_ret = IS_LEFT ? 1 : -1;
} else if (ret_code == OB_ERR_MIN_VALUE) {
cmp_ret = IS_LEFT ? -1 : 1;
} else {
ret = ret_code;
}
return ret;
}
void *ObInplaceAllocator::alloc(const int64_t size)
{
void *mem = NULL;