Fix row comparison wrong result of decimal int type
This commit is contained in:
@ -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;
|
||||
|
||||
Reference in New Issue
Block a user