From 9275c0cdfb76a0ca00e0e1553c139f56b1470b5f Mon Sep 17 00:00:00 2001 From: Au_Miner <358671982@qq.com> Date: Sun, 12 Apr 2026 22:40:02 +0800 Subject: [PATCH] [FLINK-39424][table] Setting LIKE does not support default escape characters --- docs/data/sql_functions.yml | 4 ++-- docs/data/sql_functions_zh.yml | 4 ++-- flink-python/pyflink/table/expression.py | 6 +++--- .../apache/flink/table/api/internal/BaseExpressions.java | 4 ++-- .../org/apache/flink/table/functions/SqlLikeUtils.java | 2 +- .../table/planner/calcite/FlinkSqlLikeUtilsTest.java | 4 ++-- .../table/planner/expressions/ScalarFunctionsTest.scala | 8 ++++---- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/data/sql_functions.yml b/docs/data/sql_functions.yml index 7ef571fc9c555..93baa65e3d1d4 100644 --- a/docs/data/sql_functions.yml +++ b/docs/data/sql_functions.yml @@ -50,9 +50,9 @@ comparison: description: By default (or with the ASYMMETRIC keyword), returns TRUE if value1 is less than value2 or greater than value3. With the SYMMETRIC keyword, returns TRUE if value1 is not inclusively between value2 and value3. When either value2 or value3 is NULL, returns TRUE or UNKNOWN. E.g., 12 NOT BETWEEN 15 AND 12 returns TRUE; 12 NOT BETWEEN SYMMETRIC 15 AND 12 returns FALSE; 12 NOT BETWEEN NULL AND 15 returns UNKNOWN; 12 NOT BETWEEN 15 AND NULL returns TRUE; 12 NOT BETWEEN SYMMETRIC 12 AND NULL returns UNKNOWN. - sql: string1 LIKE string2 [ ESCAPE char ] table: string1.like(string2[, char]) - description: Returns TRUE if string1 matches pattern string2; returns UNKNOWN if string1 or string2 is NULL. An escape character consisting of a single char can be defined if necessary, `\` by default. + description: Returns TRUE if string1 matches pattern string2; returns UNKNOWN if string1 or string2 is NULL. An escape character consisting of a single char can be defined using the ESCAPE clause if necessary. There is no default escape character. - sql: string1 NOT LIKE string2 [ ESCAPE char ] - description: Returns TRUE if string1 does not match pattern string2; returns UNKNOWN if string1 or string2 is NULL. An escape character consisting of a single char can be defined if necessary, `\` by default. + description: Returns TRUE if string1 does not match pattern string2; returns UNKNOWN if string1 or string2 is NULL. An escape character consisting of a single char can be defined using the ESCAPE clause if necessary. There is no default escape character. - sql: string1 SIMILAR TO string2 [ ESCAPE char ] table: string1.similar(string2) description: Returns TRUE if string1 matches SQL regular expression string2; returns UNKNOWN if string1 or string2 is NULL. An escape character can be defined if necessary. The escape character has not been supported yet. diff --git a/docs/data/sql_functions_zh.yml b/docs/data/sql_functions_zh.yml index dde3259666b52..df74194ff9003 100644 --- a/docs/data/sql_functions_zh.yml +++ b/docs/data/sql_functions_zh.yml @@ -72,11 +72,11 @@ comparison: table: string1.like(string2[, char]) description: | 如果 string1 匹配 string2 返回 `TRUE`;如果 string1 或 string2 为 `NULL` 返回 `UNKNOWN`。 - 如果需要可以定义包含单个字符的转义字符,默认为 `\`。 + 如果需要,可以通过 ESCAPE 子句定义包含单个字符的转义字符。默认没有转义字符。 - sql: string1 NOT LIKE string2 [ ESCAPE char ] description: | 如果 string1 与 string2 不匹配返回 `TRUE`;如果 string1 或 string2 为 `NULL` 返回 `UNKNOWN`。 - 如果需要可以定义包含单个字符的转义字符,默认为 `\`。 + 如果需要,可以通过 ESCAPE 子句定义包含单个字符的转义字符。默认没有转义字符。 - sql: string1 SIMILAR TO string2 [ ESCAPE char ] table: string1.similar(string2) description: | diff --git a/flink-python/pyflink/table/expression.py b/flink-python/pyflink/table/expression.py index 04649a6472757..9e1711dc4558d 100644 --- a/flink-python/pyflink/table/expression.py +++ b/flink-python/pyflink/table/expression.py @@ -1219,10 +1219,10 @@ def like(self, pattern: Union[str, 'Expression[str]'] = None, escape=None) -> 'Expression[bool]': """ - Returns true, if a string matches the specified LIKE pattern + Returns true, if a string matches the specified LIKE pattern. e.g. 'Jo_n%' matches all strings that start with 'Jo(arbitrary letter)n'. - An escape character consisting of a single char can be defined if necessary, - '\\' by default. + An escape character consisting of a single char can be defined if necessary. + There is no default escape character. """ if escape is None: return _binary_op("like")(self, pattern) diff --git a/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/api/internal/BaseExpressions.java b/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/api/internal/BaseExpressions.java index 94fbd7c101d49..27921d4105df3 100644 --- a/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/api/internal/BaseExpressions.java +++ b/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/api/internal/BaseExpressions.java @@ -1135,8 +1135,8 @@ public OutType initCap() { } /** - * Returns true, if a string matches the specified LIKE pattern with default escape character - * '/'. + * Returns true, if a string matches the specified LIKE pattern. There is no default escape + * character. * *
e.g. "Jo_n%" matches all strings that start with "Jo(arbitrary letter)n" */ diff --git a/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/functions/SqlLikeUtils.java b/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/functions/SqlLikeUtils.java index f0b09d314183d..85977d64bd3de 100644 --- a/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/functions/SqlLikeUtils.java +++ b/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/functions/SqlLikeUtils.java @@ -97,7 +97,7 @@ public static String sqlToRegexLike(String sqlPattern, CharSequence escapeStr) { } escapeChar = escapeStr.charAt(0); } else { - escapeChar = '\\'; + escapeChar = 0; } return sqlToRegexLike(sqlPattern, escapeChar); } diff --git a/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/calcite/FlinkSqlLikeUtilsTest.java b/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/calcite/FlinkSqlLikeUtilsTest.java index 86099925f8983..c081b5adc7c64 100644 --- a/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/calcite/FlinkSqlLikeUtilsTest.java +++ b/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/calcite/FlinkSqlLikeUtilsTest.java @@ -36,9 +36,9 @@ void testSqlLike() { assertThat(SqlLikeUtils.like("abcd", "a.*d", "\\")).isEqualTo(false); assertThat(SqlLikeUtils.like("abcde", "%c.e", "\\")).isEqualTo(false); - // default escape character + // no default escape character - backslash is treated as a literal character assertThat(SqlLikeUtils.like("a-c", "a\\_c")).isEqualTo(false); - assertThat(SqlLikeUtils.like("a_c", "a\\_c")).isEqualTo(true); + assertThat(SqlLikeUtils.like("a_c", "a\\_c")).isEqualTo(false); // -------------------------------- sqlToRegexLike ---------------------------------------- diff --git a/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/expressions/ScalarFunctionsTest.scala b/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/expressions/ScalarFunctionsTest.scala index 2f8ef53d0c42b..ad9bb7358ef75 100644 --- a/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/expressions/ScalarFunctionsTest.scala +++ b/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/expressions/ScalarFunctionsTest.scala @@ -408,10 +408,10 @@ class ScalarFunctionsTest extends ScalarTypesTestBase { testAllApis("abcxxxdef".like("%abc%qef%"), "'abcxxxdef' LIKE '%abc%qef%'", "FALSE") testAllApis("abcxxxdef".like("abc%qef"), "'abcxxxdef' LIKE 'abc%qef'", "FALSE") - // reported in FLINK-36100 + // reported in FLINK-36100 - without ESCAPE clause, '\' is a literal character testAllApis("TE_ST".like("%E_S%"), "'TE_ST' LIKE '%E_S%'", "TRUE") testAllApis("TE-ST".like("%E_S%"), "'TE-ST' LIKE '%E_S%'", "TRUE") - testAllApis("TE_ST".like("%E\\_S%"), "'TE_ST' LIKE '%E\\_S%'", "TRUE") + testAllApis("TE_ST".like("%E\\_S%"), "'TE_ST' LIKE '%E\\_S%'", "FALSE") testAllApis("TE-ST".like("%E\\_S%"), "'TE-ST' LIKE '%E\\_S%'", "FALSE") } @@ -420,10 +420,10 @@ class ScalarFunctionsTest extends ScalarTypesTestBase { testAllApis(!'f0.like("Th_s%"), "f0 NOT LIKE 'Th_s%'", "FALSE") testAllApis(!'f0.like("%is a%"), "f0 NOT LIKE '%is a%'", "FALSE") - // reported in FLINK-36100 + // reported in FLINK-36100 - without ESCAPE clause, '\' is a literal character testSqlApi("'TE_ST' NOT LIKE '%E_S%'", "FALSE") testSqlApi("'TE-ST' NOT LIKE '%E_S%'", "FALSE") - testSqlApi("'TE_ST' NOT LIKE '%E\\_S%'", "FALSE") + testSqlApi("'TE_ST' NOT LIKE '%E\\_S%'", "TRUE") testSqlApi("'TE-ST' NOT LIKE '%E\\_S%'", "TRUE") }