diff --git a/src/query/src/qFilterfunc.c b/src/query/src/qFilterfunc.c index 1c1ec21d653b5b96fe792aa05641191a441b8e8d..bf6cc01eea748f09c14c5ee1cc65fd8b7d88c7b6 100644 --- a/src/query/src/qFilterfunc.c +++ b/src/query/src/qFilterfunc.c @@ -183,7 +183,17 @@ bool likeOperator(SColumnFilterElem *pFilter, const char *minval, const char *ma return patternMatch((char *)pFilter->filterInfo.pz, varDataVal(minval), varDataLen(minval), &info) == TSDB_PATTERN_MATCH; } else if (type == TSDB_DATA_TYPE_NCHAR) { SPatternCompareInfo info = PATTERN_COMPARE_INFO_INITIALIZER; - return WCSPatternMatch((wchar_t*)pFilter->filterInfo.pz, varDataVal(minval), varDataLen(minval)/TSDB_NCHAR_SIZE, &info) == TSDB_PATTERN_MATCH; + size_t size = (size_t)(pFilter->filterInfo.len / TSDB_NCHAR_SIZE); + void *pz = calloc(size + 1, TSDB_NCHAR_SIZE); + if (pz == NULL) { + return false; + } + + memcpy(pz, (void *)pFilter->filterInfo.pz, size * TSDB_NCHAR_SIZE); + int32_t ret = WCSPatternMatch((wchar_t *)pz, size, varDataVal(minval), varDataLen(minval) / TSDB_NCHAR_SIZE, &info, true); + free(pz); + + return ret == TSDB_PATTERN_MATCH; } else { return false; } diff --git a/src/util/inc/tcompare.h b/src/util/inc/tcompare.h index be62ce0a659d0e07d904cac4f994b4639cd18917..6b46a529077db8d9be2512caaf0f8773233b3e7f 100644 --- a/src/util/inc/tcompare.h +++ b/src/util/inc/tcompare.h @@ -44,7 +44,7 @@ typedef struct SPatternCompareInfo { int patternMatch(const char *pattern, const char *str, size_t size, const SPatternCompareInfo *pInfo); -int WCSPatternMatch(const wchar_t *pattern, const wchar_t *str, size_t size, const SPatternCompareInfo *pInfo); +int WCSPatternMatch(wchar_t *pattern, size_t paSize, wchar_t *str, size_t size, const SPatternCompareInfo *pInfo, const bool preProc); int32_t doCompare(const char* a, const char* b, int32_t type, size_t size); diff --git a/src/util/src/tcompare.c b/src/util/src/tcompare.c index 1cfc0c3873a438699c342a7dd4a4b1a8efd32878..ad5e98c33a5262befdad482ae90f685a5b19b88a 100644 --- a/src/util/src/tcompare.c +++ b/src/util/src/tcompare.c @@ -321,7 +321,7 @@ int patternMatch(const char *patterStr, const char *str, size_t size, const SPat return (str[j] == 0 || j >= size) ? TSDB_PATTERN_MATCH : TSDB_PATTERN_NOMATCH; } -int WCSPatternMatch(const wchar_t *patterStr, const wchar_t *str, size_t size, const SPatternCompareInfo *pInfo) { +int WCSPatternMatch(wchar_t *patterStr, size_t paSize, wchar_t *str, size_t size, const SPatternCompareInfo *pInfo, const bool preProc) { wchar_t c, c1; wchar_t matchOne = L'_'; // "_" wchar_t matchAll = L'%'; // "%" @@ -329,14 +329,61 @@ int WCSPatternMatch(const wchar_t *patterStr, const wchar_t *str, size_t size, c int32_t i = 0; int32_t j = 0; +#ifdef WINDOWS + if (preProc) { + size_t realPaSize = paSize * sizeof(wchar_t); + size_t realSize = size * sizeof(wchar_t); + size_t cur = 0; + + while (i < realPaSize) { + if (patterStr[i] == 0) { + i++; + continue; + } + + if (cur != i) { + patterStr[++cur] = patterStr[i]; + } + + i++; + } + + if (cur < realPaSize) { + patterStr[++cur] = 0; + } + + cur = 0; + i = 0; + + while (i < realSize) { + if (str[i] == 0) { + i++; + continue; + } + + if (cur != i) { + str[++cur] = str[i]; + } + + i++; + } + + if (cur < realSize) { + str[++cur] = 0; + } + + i = 0; + } +#endif + while ((c = patterStr[i++]) != 0) { if (c == matchAll) { /* Match "%" */ - while ((c = patterStr[i++]) == matchAll || c == matchOne) { if (c == matchOne && (j >= size || str[j++] == 0)) { return TSDB_PATTERN_NOWILDCARDMATCH; } } + if (c == 0) { return TSDB_PATTERN_MATCH; } @@ -350,7 +397,7 @@ int WCSPatternMatch(const wchar_t *patterStr, const wchar_t *str, size_t size, c break; } - int32_t ret = WCSPatternMatch(&patterStr[i], ++str, size - n - 1, pInfo); + int32_t ret = WCSPatternMatch(&patterStr[i], paSize - i - 1, ++str, size - n - 1, pInfo, false); if (ret != TSDB_PATTERN_NOMATCH) { return ret; } @@ -465,7 +512,9 @@ int32_t compareWStrPatternComp(const void* pLeft, const void* pRight) { memcpy(pattern, varDataVal(pRight), varDataLen(pRight)); memcpy(str, varDataVal(pLeft), size * sizeof(wchar_t)); - int32_t ret = WCSPatternMatch(pattern, str, size, &pInfo); + size_t len = varDataLen(pRight)/TSDB_NCHAR_SIZE; + + int32_t ret = WCSPatternMatch(pattern, len, str, size, &pInfo, true); free(pattern); free(str); diff --git a/tests/pytest/query/queryLike.py b/tests/pytest/query/queryLike.py index b3916ed84db1d558e4b95f62c2def19deee75944..44b0ba8756bafaae11977e7b1b282ddc9fd3bf2c 100644 --- a/tests/pytest/query/queryLike.py +++ b/tests/pytest/query/queryLike.py @@ -161,6 +161,17 @@ class TDTestCase: tdSql.query("select * from st where tagg like 'tag\_\__\_';") tdSql.checkData(0,0, "tag__a_") + tdSql.execute("create table stb(ts timestamp, c0 int) tags(t0 nchar(64))") + tdSql.execute("insert into tb1 using stb tags('测试ABCabc') values(now, 1)") + tdSql.query("select * from tb1 where t0 like '%试AB%'") + tdSql.checkRows(1) + + tdSql.query("select * from tb1 where t0 like '测试AB%'") + tdSql.checkRows(1) + + tdSql.query("select * from tb1 where t0 like '%ABCabc'") + tdSql.checkRows(1) + os.system("rm -rf ./*.py.sql") def stop(self):