This is an automated email from the ASF dual-hosted git repository.
kxiao pushed a commit to branch branch-2.0
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-2.0 by this push:
new 1b7c9149360 [fix](like_func) incorrect result of like with
'NO_BACKSLASH_ESCAPES' mode(#27842) (#27851)
1b7c9149360 is described below
commit 1b7c9149360c3a9c2d233d729a13cff1b0ebe8fa
Author: Jerry Hu <[email protected]>
AuthorDate: Fri Dec 1 20:21:06 2023 +0800
[fix](like_func) incorrect result of like with 'NO_BACKSLASH_ESCAPES'
mode(#27842) (#27851)
---
be/src/vec/functions/like.cpp | 43 +++++++++++--------
fe/fe-core/src/main/jflex/sql_scanner.flex | 10 +++--
.../test_like_no_backslash_escapes_mode.out | 7 +++
.../test_like_no_backslash_escapes_mode.groovy | 50 ++++++++++++++++++++++
4 files changed, 89 insertions(+), 21 deletions(-)
diff --git a/be/src/vec/functions/like.cpp b/be/src/vec/functions/like.cpp
index 8851b777fee..add09f845a6 100644
--- a/be/src/vec/functions/like.cpp
+++ b/be/src/vec/functions/like.cpp
@@ -453,24 +453,30 @@ void FunctionLike::convert_like_pattern(LikeSearchState*
state, const std::strin
bool is_escaped = false;
for (size_t i = 0; i < pattern.size(); ++i) {
- if (!is_escaped && pattern[i] == '%') {
- re_pattern->append(".*");
- } else if (!is_escaped && pattern[i] == '_') {
- re_pattern->append(".");
- // check for escape char before checking for regex special chars,
they might overlap
- } else if (!is_escaped && pattern[i] == state->escape_char) {
- is_escaped = true;
- } else if (pattern[i] == '.' || pattern[i] == '[' || pattern[i] == ']'
||
- pattern[i] == '{' || pattern[i] == '}' || pattern[i] == '('
||
- pattern[i] == ')' || pattern[i] == '\\' || pattern[i] ==
'*' ||
- pattern[i] == '+' || pattern[i] == '?' || pattern[i] == '|'
||
- pattern[i] == '^' || pattern[i] == '$') {
- // escape all regex special characters; see list at
- re_pattern->append("\\");
- re_pattern->append(1, pattern[i]);
- is_escaped = false;
+ if (!is_escaped) {
+ switch (pattern[i]) {
+ case '%':
+ re_pattern->append(".*");
+ break;
+ case '_':
+ re_pattern->append(".");
+ break;
+ default:
+ is_escaped = pattern[i] == state->escape_char;
+ if (!is_escaped) {
+ re_pattern->append(1, pattern[i]);
+ }
+ break;
+ }
} else {
- // regular character or escaped special character
+ if (pattern[i] == '.' || pattern[i] == '[' || pattern[i] == ']' ||
pattern[i] == '{' ||
+ pattern[i] == '}' || pattern[i] == '(' || pattern[i] == ')' ||
pattern[i] == '\\' ||
+ pattern[i] == '*' || pattern[i] == '+' || pattern[i] == '?' ||
pattern[i] == '|' ||
+ pattern[i] == '^' || pattern[i] == '$') {
+ re_pattern->append("\\");
+ } else if (pattern[i] != '%' && pattern[i] != '_') {
+ re_pattern->append("\\\\");
+ }
re_pattern->append(1, pattern[i]);
is_escaped = false;
}
@@ -634,7 +640,8 @@ Status FunctionLike::open(FunctionContext* context,
FunctionContext::FunctionSta
opts.set_dot_nl(true);
state->search_state.regex = std::make_unique<RE2>(re_pattern,
opts);
if (!state->search_state.regex->ok()) {
- return Status::InternalError("Invalid regex expression:
{}", pattern_str);
+ return Status::InternalError("Invalid regex expression:
{}(origin: {})",
+ re_pattern, pattern_str);
}
}
diff --git a/fe/fe-core/src/main/jflex/sql_scanner.flex
b/fe/fe-core/src/main/jflex/sql_scanner.flex
index a3f9498fd7e..4a19494ce80 100644
--- a/fe/fe-core/src/main/jflex/sql_scanner.flex
+++ b/fe/fe-core/src/main/jflex/sql_scanner.flex
@@ -572,7 +572,11 @@ import org.apache.doris.qe.SqlModeHelper;
return new Symbol(id, yyline+1, yycolumn+1, value);
}
- private static String escapeBackSlash(String str) {
+ private static String escapeBackSlash(String str, long sqlMode) {
+ if ((sqlMode & SqlModeHelper.MODE_NO_BACKSLASH_ESCAPES) != 0) {
+ return str;
+ }
+
StringWriter writer = new StringWriter();
int strLen = str.length();
for (int i = 0; i < strLen; ++i) {
@@ -732,12 +736,12 @@ EndOfLineComment = "--"
!({HintContent}|{ContainsLineTerminator}) {LineTerminato
{SingleQuoteStringLiteral} {
return newToken(SqlParserSymbols.STRING_LITERAL,
- escapeBackSlash(yytext().substring(1,
yytext().length()-1)).replaceAll("''", "'"));
+ escapeBackSlash(yytext().substring(1, yytext().length()-1),
sql_mode).replaceAll("''", "'"));
}
{DoubleQuoteStringLiteral} {
return newToken(SqlParserSymbols.STRING_LITERAL,
- escapeBackSlash(yytext().substring(1,
yytext().length()-1)).replaceAll("\"\"", "\""));
+ escapeBackSlash(yytext().substring(1, yytext().length()-1),
sql_mode).replaceAll("\"\"", "\""));
}
{CommentedHintBegin} {
diff --git
a/regression-test/data/query_p0/sql_functions/string_functions/test_like_no_backslash_escapes_mode.out
b/regression-test/data/query_p0/sql_functions/string_functions/test_like_no_backslash_escapes_mode.out
new file mode 100644
index 00000000000..13540d6ee2d
--- /dev/null
+++
b/regression-test/data/query_p0/sql_functions/string_functions/test_like_no_backslash_escapes_mode.out
@@ -0,0 +1,7 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !select1 --
+1 TIN\\PEXNB601C6UUTAB
+
+-- !select2 --
+1 TIN\\PEXNB601C6UUTAB
+
diff --git
a/regression-test/suites/query_p0/sql_functions/string_functions/test_like_no_backslash_escapes_mode.groovy
b/regression-test/suites/query_p0/sql_functions/string_functions/test_like_no_backslash_escapes_mode.groovy
new file mode 100644
index 00000000000..43a51fb31b7
--- /dev/null
+++
b/regression-test/suites/query_p0/sql_functions/string_functions/test_like_no_backslash_escapes_mode.groovy
@@ -0,0 +1,50 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+suite("test_like_no_backslash_escapes_mode") {
+
+ sql """ set sql_mode = "NO_BACKSLASH_ESCAPES"; """
+ def tbName = "test_like_no_backslash_escapes_mode_tbl"
+ sql "DROP TABLE IF EXISTS ${tbName}"
+
+ sql """
+ CREATE TABLE `${tbName}` (
+ `id` INT NULL,
+ `value` VARCHAR(100) NULL
+ ) ENGINE=OLAP
+ DUPLICATE KEY(`id`)
+ COMMENT 'OLAP'
+ DISTRIBUTED BY HASH(`id`) BUCKETS 1
+ PROPERTIES (
+ "replication_allocation" = "tag.location.default: 1"
+ );
+ """
+
+ sql """
+ INSERT INTO ${tbName} VALUES (1, "TIN\\PEXNB601C6UUTAB");
+ """
+
+ qt_select1 """
+ select * from ${tbName} where `value` like "%TIN\\PE%";
+ """
+
+ qt_select2 """
+ select * from ${tbName} where `value` = "TIN\\PEXNB601C6UUTAB";
+ """
+
+ // sql "DROP TABLE ${tbName};"
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]