[CP] fix like(nchar) bug
This commit is contained in:
@ -208,16 +208,15 @@ int ObExprLike::check_pattern_valid(const T &pattern,
|
|||||||
} else if (pre_char_is_escape) {
|
} else if (pre_char_is_escape) {
|
||||||
// If pre char is escape char, then the following char must be '_' or '%'
|
// If pre char is escape char, then the following char must be '_' or '%'
|
||||||
// Eg: select 1 from t1 where 'a' like 'a_a%' escape 'a'; -- it's ok
|
// Eg: select 1 from t1 where 'a' like 'a_a%' escape 'a'; -- it's ok
|
||||||
if (1 != char_len) {
|
ObString percent_str = ObCharsetUtils::get_const_str(coll_type, '%');
|
||||||
ret = OB_ERR_INVALID_CHAR_FOLLOWING_ESCAPE_CHAR;
|
ObString underline_str = ObCharsetUtils::get_const_str(coll_type, '_');
|
||||||
LOG_WARN("missing or illegal character following the escape character",
|
const ObString pattern_char = ObString(char_len, buf_start);
|
||||||
K(escape_val), K(pattern_val), K(ret));
|
if (0 == pattern_char.compare(percent_str) || 0 == pattern_char.compare(underline_str)) {
|
||||||
} else if ('%' == *buf_start || '_' == *buf_start) {
|
|
||||||
// it's ok
|
// it's ok
|
||||||
} else {
|
} else {
|
||||||
ret = OB_ERR_INVALID_CHAR_FOLLOWING_ESCAPE_CHAR;
|
ret = OB_ERR_INVALID_CHAR_FOLLOWING_ESCAPE_CHAR;
|
||||||
LOG_WARN("missing or illegal character following the escape character",
|
LOG_WARN("missing or illegal character following the escape character",
|
||||||
K(escape_val), K(pattern_val), K(ret));
|
K(escape_val), K(pattern_val), K(pattern_char), K(ret));
|
||||||
}
|
}
|
||||||
pre_char_is_escape = false;
|
pre_char_is_escape = false;
|
||||||
}
|
}
|
||||||
@ -361,6 +360,7 @@ int ObExprLike::set_instr_info(ObIAllocator *exec_allocator,
|
|||||||
//when there are "_" or escape in pattern
|
//when there are "_" or escape in pattern
|
||||||
//the case can not be optimized.
|
//the case can not be optimized.
|
||||||
use_instr_mode = false;
|
use_instr_mode = false;
|
||||||
|
// since cs_type is CS_TYPE_UTF8MB4_BIN, length of '%' must be 1.
|
||||||
} else if ((1 == char_len && '%' == *buf_start)) { //percent sign
|
} else if ((1 == char_len && '%' == *buf_start)) { //percent sign
|
||||||
percent_sign_exist = true;
|
percent_sign_exist = true;
|
||||||
if (OB_LIKELY(instr_len > 0)) {
|
if (OB_LIKELY(instr_len > 0)) {
|
||||||
@ -822,12 +822,16 @@ struct ObNonInstrModeMatcher
|
|||||||
inline int64_t operator() (const ObCollationType coll_type,
|
inline int64_t operator() (const ObCollationType coll_type,
|
||||||
const ObString &text_val,
|
const ObString &text_val,
|
||||||
const ObString &pattern_val,
|
const ObString &pattern_val,
|
||||||
int32_t escape_wc)
|
int32_t escape_wc,
|
||||||
|
int &ret)
|
||||||
{
|
{
|
||||||
int64_t res = 0;
|
int64_t res = 0;
|
||||||
if (OB_UNLIKELY(text_val.length() <= 0 && pattern_val.length() <= 0)) {
|
if (OB_UNLIKELY(text_val.length() <= 0 && pattern_val.length() <= 0)) {
|
||||||
// empty string
|
// empty string
|
||||||
res = 1;
|
res = 1;
|
||||||
|
} else if (OB_UNLIKELY(CS_TYPE_UTF8MB4_BIN != coll_type && escape_wc == static_cast<int32_t>('%'))) {
|
||||||
|
ret = OB_NOT_SUPPORTED;
|
||||||
|
LOG_USER_ERROR(OB_NOT_SUPPORTED, "escape %");
|
||||||
} else {
|
} else {
|
||||||
bool b = ObCharset::wildcmp(coll_type, text_val, pattern_val, escape_wc,
|
bool b = ObCharset::wildcmp(coll_type, text_val, pattern_val, escape_wc,
|
||||||
static_cast<int32_t>('_'), static_cast<int32_t>('%'));
|
static_cast<int32_t>('_'), static_cast<int32_t>('%'));
|
||||||
@ -867,7 +871,7 @@ int ObExprLike::match_text_batch(BATCH_EVAL_FUNC_ARG_DECL,
|
|||||||
res_datums[i].set_int(res);
|
res_datums[i].set_int(res);
|
||||||
} else {
|
} else {
|
||||||
res_datums[i].set_int(ObNonInstrModeMatcher()(coll_type, text_datums[i].get_string(),
|
res_datums[i].set_int(ObNonInstrModeMatcher()(coll_type, text_datums[i].get_string(),
|
||||||
pattern_val, escape_wc));
|
pattern_val, escape_wc, ret));
|
||||||
}
|
}
|
||||||
} else { // text tc
|
} else { // text tc
|
||||||
ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx);
|
ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx);
|
||||||
@ -886,7 +890,7 @@ int ObExprLike::match_text_batch(BATCH_EVAL_FUNC_ARG_DECL,
|
|||||||
res_datums[i].set_int(res);
|
res_datums[i].set_int(res);
|
||||||
} else {
|
} else {
|
||||||
res_datums[i].set_int(ObNonInstrModeMatcher()(coll_type, text_val,
|
res_datums[i].set_int(ObNonInstrModeMatcher()(coll_type, text_val,
|
||||||
pattern_val, escape_wc));
|
pattern_val, escape_wc, ret));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -909,7 +913,7 @@ int ObExprLike::match_text_batch(BATCH_EVAL_FUNC_ARG_DECL,
|
|||||||
res_datums[i].set_int(res);
|
res_datums[i].set_int(res);
|
||||||
} else {
|
} else {
|
||||||
res_datums[i].set_int(ObNonInstrModeMatcher()(coll_type, text_datums[i].get_string(),
|
res_datums[i].set_int(ObNonInstrModeMatcher()(coll_type, text_datums[i].get_string(),
|
||||||
pattern_val, escape_wc));
|
pattern_val, escape_wc, ret));
|
||||||
}
|
}
|
||||||
} else { // text tc
|
} else { // text tc
|
||||||
ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx);
|
ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx);
|
||||||
@ -929,7 +933,7 @@ int ObExprLike::match_text_batch(BATCH_EVAL_FUNC_ARG_DECL,
|
|||||||
res_datums[i].set_int(res);
|
res_datums[i].set_int(res);
|
||||||
} else {
|
} else {
|
||||||
res_datums[i].set_int(ObNonInstrModeMatcher()(coll_type, text_val,
|
res_datums[i].set_int(ObNonInstrModeMatcher()(coll_type, text_val,
|
||||||
pattern_val, escape_wc));
|
pattern_val, escape_wc, ret));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -229,9 +229,15 @@ int ObExprLike::calc_with_non_instr_mode(T &result,
|
|||||||
} else if (text_val.length() <= 0 && pattern_val.length() <= 0) {
|
} else if (text_val.length() <= 0 && pattern_val.length() <= 0) {
|
||||||
// empty string
|
// empty string
|
||||||
result.set_int(1);
|
result.set_int(1);
|
||||||
|
} else if (OB_UNLIKELY(CS_TYPE_UTF8MB4_BIN != coll_type && escape_wc == static_cast<int32_t>('%'))) {
|
||||||
|
// when cs_type is not utf8mb4_bin and escape = %, there is a bug of wildcmp
|
||||||
|
ret = OB_NOT_SUPPORTED;
|
||||||
|
LOG_USER_ERROR(OB_NOT_SUPPORTED, "escape %");
|
||||||
} else {
|
} else {
|
||||||
bool b = ObCharset::wildcmp(coll_type, text_val, pattern_val, escape_wc,
|
bool b = ObCharset::wildcmp(coll_type, text_val, pattern_val, escape_wc,
|
||||||
static_cast<int32_t>('_'), static_cast<int32_t>('%'));
|
static_cast<int32_t>('_'), static_cast<int32_t>('%'));
|
||||||
|
SQL_LOG(DEBUG, "calc_with_non_instr_mode1", K(escape_coll), K(escape_val), K(escape_wc), K(pattern_val),
|
||||||
|
K(coll_type), KPHEX(text_val.ptr(), text_val.length()), KPHEX(pattern_val.ptr(), pattern_val.length()), K(b));
|
||||||
result.set_int(static_cast<int64_t>(b));
|
result.set_int(static_cast<int64_t>(b));
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@ -7506,8 +7506,7 @@ int ObQueryRange::get_like_range(const ObObj &pattern,
|
|||||||
} else if (OB_ISNULL(escape_str.ptr())) {
|
} else if (OB_ISNULL(escape_str.ptr())) {
|
||||||
ret = OB_ERR_UNEXPECTED;
|
ret = OB_ERR_UNEXPECTED;
|
||||||
LOG_WARN("Escape str should not be NULL", K(ret));
|
LOG_WARN("Escape str should not be NULL", K(ret));
|
||||||
} else if (OB_UNLIKELY((lib::is_oracle_mode() && 1 != escape_str.length())
|
} else if (OB_UNLIKELY(1 > escape_str.length())) {
|
||||||
|| (!lib::is_oracle_mode() && 1 > escape_str.length()))) {
|
|
||||||
ret = OB_INVALID_ARGUMENT;
|
ret = OB_INVALID_ARGUMENT;
|
||||||
LOG_WARN("failed to check escape length", K(escape_str), K(escape_str.length()));
|
LOG_WARN("failed to check escape length", K(escape_str), K(escape_str.length()));
|
||||||
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "ESCAPE");
|
LOG_USER_ERROR(OB_INVALID_ARGUMENT, "ESCAPE");
|
||||||
|
|||||||
Reference in New Issue
Block a user