fix bug of weight_string

This commit is contained in:
AntiTopQuark
2023-01-05 08:16:35 +00:00
committed by ob-robot
parent d8a6142152
commit a0b1894058
2 changed files with 76 additions and 51 deletions

View File

@ -19475,7 +19475,7 @@ static size_t ob_strnxfrm_gb18030(const ObCharsetInfo *cs, uchar *dst,
++src; ++src;
} }
} }
return ob_strxfrm_pad(cs, ds, dst, de, nweights, flags); return ob_strxfrm_pad_desc_and_reverse(cs, ds, dst, de, nweights, flags, 0);
} }
size_t ob_varlen_encoding_gb18030_for_memcmp(const struct ObCharsetInfo* cs, size_t ob_varlen_encoding_gb18030_for_memcmp(const struct ObCharsetInfo* cs,

View File

@ -21,6 +21,8 @@
#include "lib/oblog/ob_log.h" #include "lib/oblog/ob_log.h"
#include "sql/engine/expr/ob_datum_cast.h" #include "sql/engine/expr/ob_datum_cast.h"
#include "ob_expr_util.h" #include "ob_expr_util.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/session/ob_sql_session_info.h"
using namespace oceanbase::common; using namespace oceanbase::common;
@ -46,11 +48,6 @@ int ObExprWeightString::calc_result_typeN(ObExprResType &type,
if (NOT_ROW_DIMENSION != row_dimension_ || ObMaxType == types_stack[0].get_type()) { if (NOT_ROW_DIMENSION != row_dimension_ || ObMaxType == types_stack[0].get_type()) {
ret = OB_ERR_INVALID_TYPE_FOR_OP; ret = OB_ERR_INVALID_TYPE_FOR_OP;
} else { } else {
if (types_stack[0].get_type() > ObUNumberType && types_stack[0].get_type() != ObBitType) {
// 输入不是数字类型时
type_ctx.set_cast_mode(type_ctx.get_cast_mode() | CM_NULL_ON_WARN);
types_stack[0].set_calc_type(ObVarcharType);
}
uint64_t max_length = OB_MAX_VARBINARY_LENGTH; // The maximum length of the result of WEIGHT_STRING() uint64_t max_length = OB_MAX_VARBINARY_LENGTH; // The maximum length of the result of WEIGHT_STRING()
uint64_t result_length = types_stack[1].get_param().get_int(); uint64_t result_length = types_stack[1].get_param().get_int();
uint64_t nweight = types_stack[2].get_param().get_int(); uint64_t nweight = types_stack[2].get_param().get_int();
@ -58,8 +55,17 @@ int ObExprWeightString::calc_result_typeN(ObExprResType &type,
ObCollationLevel coll_level = CS_LEVEL_INVALID; ObCollationLevel coll_level = CS_LEVEL_INVALID;
if (as_binary) { if (as_binary) {
coll_level = CS_LEVEL_IMPLICIT; coll_level = CS_LEVEL_IMPLICIT;
type_ctx.set_cast_mode(type_ctx.get_cast_mode() | CM_NULL_ON_WARN);
types_stack[0].set_calc_type(ObVarcharType);
} else { } else {
coll_level = types_stack[0].get_collation_level(); coll_level = types_stack[0].get_collation_level();
if (types_stack[0].get_type() > ObUNumberType &&
types_stack[0].get_type() != ObBitType &&
types_stack[0].get_type() != ObYearType) {
// 输入不是数字类型时
type_ctx.set_cast_mode(type_ctx.get_cast_mode() | CM_NULL_ON_WARN);
types_stack[0].set_calc_type(ObVarcharType);
}
} }
ObCollationType collation_type = types_stack[0].get_collation_type(); ObCollationType collation_type = types_stack[0].get_collation_type();
const ObCharsetInfo *cs = ObCharset::get_charset(collation_type); const ObCharsetInfo *cs = ObCharset::get_charset(collation_type);
@ -106,58 +112,77 @@ int ObExprWeightString::eval_weight_string(const ObExpr &expr, ObEvalCtx &ctx, O
KP(nweights_arg), KP(nweights_arg),
KP(flags_arg), KP(flags_arg),
KP(as_binary_arg)); KP(as_binary_arg));
} else if (arg->is_null() || expr.args_[0]->datum_meta_.type_ <= ObUNumberType || expr.args_[0]->datum_meta_.type_ == ObBitType) {
// The input string is NULL or numeric
res_datum.set_null();
} else if (arg->get_string().length() == 0 && arg->get_string().ptr() == nullptr) {
res_datum.set_string(nullptr,0);
} else { } else {
const ObString str = arg->get_string(); const ObString str = arg->get_string();
uint64_t result_length = result_length_arg->get_int(); uint64_t result_length = result_length_arg->get_int();
uint64_t nweights = nweights_arg->get_int(); uint64_t nweights = nweights_arg->get_int();
uint64_t flags = flags_arg->get_int(); uint64_t flags = flags_arg->get_int();
bool as_binary = as_binary_arg->get_int(); bool as_binary = as_binary_arg->get_int();
int64_t max_allowed_packet = 0;
// Get the character set and collation information of the input string ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session();
ObCollationType collation_type = CS_TYPE_INVALID; if (arg->is_null()) {
if (as_binary) { // The input string is NULL
collation_type = CS_TYPE_BINARY; res_datum.set_null();
} else if (!as_binary && (expr.args_[0]->datum_meta_.type_ <= ObUNumberType ||
expr.args_[0]->datum_meta_.type_ == ObBitType ||
expr.args_[0]->datum_meta_.type_ == ObYearType)) {
res_datum.set_null();
} else if (arg->get_string().empty() && nweights == 0) {
res_datum.set_string(nullptr,0);
} else { } else {
collation_type = expr.args_[0]->datum_meta_.cs_type_; if (OB_FAIL(session->get_max_allowed_packet(max_allowed_packet))) {
} if (OB_ENTRY_NOT_EXIST == ret) {
const ObCharsetInfo *cs = ObCharset::get_charset(collation_type); ret = OB_SUCCESS;
flags = ob_strxfrm_flag_normalize(flags, cs->levels_for_order); max_allowed_packet = OB_MAX_VARCHAR_LENGTH;
// calc the length of result } else {
size_t frm_length = 0; LOG_WARN("Failed to get max allow packet size", K(ret));
size_t tmp_length = 0; }
if (result_length > 0) { }
tmp_length = result_length; // Get the character set and collation information of the input string
} else { ObCollationType collation_type = CS_TYPE_INVALID;
tmp_length = cs->coll->strnxfrmlen(cs, cs->mbmaxlen*MAX(str.length() , nweights)); if (as_binary) {
} collation_type = CS_TYPE_BINARY;
int used_nweights = nweights; } else {
size_t input_length = str.length(); collation_type = expr.args_[0]->datum_meta_.cs_type_;
if (used_nweights) { }
//truncate input string const ObCharsetInfo *cs = ObCharset::get_charset(collation_type);
input_length = std::min(input_length, cs->cset->charpos(cs, str.ptr(), str.ptr() + str.length(), nweights)); flags = ob_strxfrm_flag_normalize(flags, cs->levels_for_order);
} else { // calc the length of result
//calc char length size_t frm_length = 0;
used_nweights = cs->cset->numchars(cs, str.ptr(), str.ptr() + str.length()); size_t tmp_length = 0;
} if (result_length > 0) {
bool is_valid_unicode_tmp = 1; tmp_length = result_length;
char *out_buf = expr.get_str_res_mem(ctx, tmp_length); } else {
if (OB_ISNULL(out_buf)) { tmp_length = cs->coll->strnxfrmlen(cs, cs->mbmaxlen*MAX(str.length() , nweights));
ret = OB_ALLOCATE_MEMORY_FAILED; }
} else { if (tmp_length >= max_allowed_packet) {
frm_length = cs->coll->strnxfrm(cs, res_datum.set_null();
reinterpret_cast<uchar *>(out_buf), } else {
tmp_length, int used_nweights = nweights;
used_nweights, size_t input_length = str.length();
reinterpret_cast<const uchar *>(str.ptr()), if (used_nweights) {
input_length, //truncate input string
flags, input_length = std::min(input_length, cs->cset->charpos(cs, str.ptr(), str.ptr() + str.length(), nweights));
&is_valid_unicode_tmp); } else {
res_datum.set_string(out_buf,frm_length); //calc char length
used_nweights = cs->cset->numchars(cs, str.ptr(), str.ptr() + str.length());
}
bool is_valid_unicode_tmp = 1;
char *out_buf = expr.get_str_res_mem(ctx, tmp_length);
if (OB_ISNULL(out_buf)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
} else {
frm_length = cs->coll->strnxfrm(cs,
reinterpret_cast<uchar *>(out_buf),
tmp_length,
used_nweights,
reinterpret_cast<const uchar *>(str.ptr()),
input_length,
flags,
&is_valid_unicode_tmp);
res_datum.set_string(out_buf,frm_length);
}
}
} }
} }
return ret; return ret;