Fix system function compatibility bugs

This commit is contained in:
2149
2023-08-02 13:42:35 +00:00
committed by ob-robot
parent 1653ffdd23
commit 8063cbeebb
6 changed files with 300 additions and 125 deletions

View File

@ -44,6 +44,7 @@ int ObExprMakeSet::calc_result_typeN(ObExprResType &type,
} else {
// set expected type of parameter
ObLength max_len = 0;
type_ctx.set_cast_mode(type_ctx.get_cast_mode() | CM_STRING_INTEGER_TRUNC);
types[0].set_calc_type(ObIntType);
for (int64_t i = 1; i < param_num; ++i) {
types[i].set_calc_type(ObVarcharType);

View File

@ -300,13 +300,37 @@ int ObExprOracleDecode::calc_result_typeN(ObExprResType &type,
//deduce string length
if (ob_is_string_type(type.get_type()) || ob_is_raw(type.get_type())) {
ObLength len = -1;
for (int64_t i = 2; i < param_num; i += 2 /*skip conditions */) {
if (types_stack[i].get_length() > len) {
len = types_stack[i].get_length();
if (is_oracle_mode() && (ob_is_string_tc(type.get_type()) || ob_is_raw(type.get_type()))) {
ObLength deduced_len = -1;
if (OB_ISNULL(type_ctx.get_session())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("session is NULL", K(ret));
}
for (int64_t i = 2; OB_SUCC(ret) && i < param_num; i += 2 /*skip conditions */) {
if (OB_FAIL(ObExprResultTypeUtil::deduce_max_string_length_oracle(type_ctx.get_session()->get_dtc_params(),
types_stack[i], type, deduced_len, type.get_length_semantics()))) {
LOG_WARN("fail to deduce max string length", K(ret));
} else if (deduced_len > len) {
len = deduced_len;
}
}
if (OB_SUCC(ret) && has_default) {
if (OB_FAIL(ObExprResultTypeUtil::deduce_max_string_length_oracle(type_ctx.get_session()->get_dtc_params(),
types_stack[param_num - 1], type, deduced_len, type.get_length_semantics()))) {
LOG_WARN("fail to deduce max string length", K(ret));
} else if (deduced_len > len) {
len = deduced_len;
}
}
} else {
for (int64_t i = 2; i < param_num; i += 2 /*skip conditions */) {
if (types_stack[i].get_length() > len) {
len = types_stack[i].get_length();
}
}
if (has_default) {
len = static_cast<ObLength>(MAX(types_stack[param_num - 1].get_length(), len));
}
}
if (has_default) {
len = static_cast<ObLength>(MAX(types_stack[param_num - 1].get_length(), len));
}
if (all_literal && lib::is_oracle_mode()) {
if (OB_FAIL(calc_result_type_for_literal(type, types_stack, param_num, type_ctx))) {

View File

@ -653,7 +653,7 @@ int ObExprResultTypeUtil::get_arith_calc_type(ObObjType &calc_type,
int CHECK_STRING_RES_TYPE_ORACLE(const ObExprResType &type)
{
int ret = OB_SUCCESS;
if (!type.is_string_or_lob_locator_type()) {
if (!type.is_string_or_lob_locator_type() && !type.is_raw()) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("incorrect type of target type", K(ret), K(type));
} else if (type.is_blob() || type.is_blob_locator()) {
@ -663,7 +663,7 @@ int CHECK_STRING_RES_TYPE_ORACLE(const ObExprResType &type)
} else if (!ObCharset::is_valid_collation(type.get_collation_type())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("incorrect charset of target type", K(ret), K(type));
} else if (!type.is_clob() && !type.is_clob_locator() &&
} else if (!type.is_clob() && !type.is_clob_locator() && !type.is_raw() &&
LS_CHAR != type.get_length_semantics() && LS_BYTE != type.get_length_semantics()) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("incorrect length_semantics of target type", K(ret), K(type));
@ -693,6 +693,8 @@ int ObExprResultTypeUtil::deduce_max_string_length_oracle(const ObDataTypeCastPa
ObLengthSemantics length_semantics = target_type.get_length_semantics();
if (target_type.is_varchar_or_char() && (LS_BYTE == calc_ls || LS_CHAR == calc_ls)) {
length_semantics = calc_ls;
} else if (target_type.is_raw()) {
length_semantics = LS_BYTE;
}
if (OB_FAIL(CHECK_STRING_RES_TYPE_ORACLE(target_type))) {
LOG_WARN("invalid target_type", K(ret));
@ -736,6 +738,9 @@ int ObExprResultTypeUtil::deduce_max_string_length_oracle(const ObDataTypeCastPa
// clob to LS_CHAR
int64_t mbminlen = ObCharset::get_charset(target_type.get_collation_type())->mbminlen;
length = OB_MAX_ORACLE_VARCHAR_LENGTH / mbminlen;
} else if (target_type.is_raw()) {
//cast not support, return max length
length = OB_MAX_ORACLE_RAW_PL_VAR_LENGTH;
} else {
// clob to LS_BYTE
length = OB_MAX_ORACLE_VARCHAR_LENGTH;
@ -750,6 +755,12 @@ int ObExprResultTypeUtil::deduce_max_string_length_oracle(const ObDataTypeCastPa
}
length *= ObCharset::MAX_MB_LEN;
length /= ObCharset::get_charset(target_type.get_collation_type())->mbminlen;
} else if ((orig_type.is_varchar_or_char() || orig_type.is_nstring())
&& target_type.is_raw()) {
if (LS_CHAR == orig_type.get_length_semantics()) {
length *= ObCharset::get_charset(orig_type.get_collation_type())->mbmaxlen;
}
length = (length + 1) / 2;
} else if (LS_CHAR == orig_type.get_length_semantics()
&& LS_BYTE == length_semantics) {
// LS_CHAR to LS_BYTE
@ -790,7 +801,14 @@ int ObExprResultTypeUtil::deduce_max_string_length_oracle(const ObDataTypeCastPa
ascii_bytes = orig_type.get_length();
}
if (OB_SUCC(ret)) {
if (LS_BYTE == length_semantics &&
if (target_type.is_raw()) {
if (orig_type.is_raw() || orig_type.is_json()) {
length = orig_type.get_length();
} else {
//cast not support, return max length
length = OB_MAX_ORACLE_RAW_PL_VAR_LENGTH;
}
} else if (LS_BYTE == length_semantics &&
ObCharset::is_cs_nonascii(target_type.get_collation_type())) {
length = (ObLength)(ascii_bytes
* ObCharset::get_charset(target_type.get_collation_type())->mbminlen);

View File

@ -135,9 +135,9 @@ int ObExprSubstringIndex::eval_substring_index(
expr_datum.len_ = 0;
} else {
const ObString m_delim = delim.get_string();
// Static cast count to int32, compatible with mysql 5.6,
// mysql 5.6 static cast count to int32,
// actually this is a bug and fixed in mysql 8.0.
int32_t count_val = static_cast<int32_t>(count.get_int());
int64_t count_val = count.get_int();
ObString res_str;
ObExprKMPSearchCtx *kmp_ctx = NULL;
const uint64_t op_id = static_cast<uint64_t>(expr.expr_ctx_id_);
@ -180,14 +180,14 @@ int ObExprSubstringIndex::eval_substring_index_batch(const ObExpr &expr,
continue;;
}
ObString res_str;
int32_t count_val = 0;
int64_t count_val = 0;
ObDatum &text = expr.args_[0]->locate_expr_datum(ctx, i);
ObDatum &delim = expr.args_[1]->locate_expr_datum(ctx, i);
ObDatum &count = expr.args_[2]->locate_expr_datum(ctx, i);
if (OB_UNLIKELY(text.is_null() || delim.is_null() || count.is_null())) {
res[i].set_null();
} else if (0 == text.len_ || 0 == delim.len_ ||
0 == (count_val = static_cast<int32_t>(count.get_int()))) {
0 == (count_val = count.get_int())) {
// return empty string if %str or %delim is empty.
//重置null flag 防止丢失空串信息
res[i].null_ = 0;