This is an automated email from the ASF dual-hosted git repository.

snuyanzin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink.git


The following commit(s) were added to refs/heads/master by this push:
     new f03c9044268 [FLINK-39868][table-runtime] Remove per-row logging from 
`parseUrl` and `subString`
f03c9044268 is described below

commit f03c904426853ad3a62883d196b4f6b07c7ef365
Author: Ramin Gharib <[email protected]>
AuthorDate: Wed Jun 10 09:40:03 2026 +0200

    [FLINK-39868][table-runtime] Remove per-row logging from `parseUrl` and 
`subString`
---
 .../planner/functions/StringFunctionsITCase.java   | 237 ++++++++++++++++++++-
 .../planner/expressions/ScalarFunctionsTest.scala  | 162 --------------
 .../table/runtime/functions/SqlFunctionUtils.java  |   8 -
 3 files changed, 235 insertions(+), 172 deletions(-)

diff --git 
a/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/StringFunctionsITCase.java
 
b/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/StringFunctionsITCase.java
index e3b7e077aff..0fd1c53dac9 100644
--- 
a/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/StringFunctionsITCase.java
+++ 
b/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/StringFunctionsITCase.java
@@ -41,12 +41,15 @@ class StringFunctionsITCase extends BuiltInFunctionTestBase 
{
     Stream<TestSetSpec> getTestSetSpecs() {
         return Stream.of(
                         bTrimTestCases(),
+                        concatenateTestCases(),
                         eltTestCases(),
                         endsWithTestCases(),
+                        parseUrlTestCases(),
                         printfTestCases(),
                         startsWithTestCases(),
-                        translateTestCases(),
-                        concatenateTestCases())
+                        substrTestCases(),
+                        substringTestCases(),
+                        translateTestCases())
                 .flatMap(s -> s);
     }
 
@@ -752,4 +755,234 @@ class StringFunctionsITCase extends 
BuiltInFunctionTestBase {
                                 "Invalid input arguments. Expected signatures 
are:\n"
                                         + "TRANSLATE3(expr <CHARACTER_STRING>, 
fromStr <CHARACTER_STRING>, toStr <CHARACTER_STRING>)"));
     }
+
+    private Stream<TestSetSpec> parseUrlTestCases() {
+        return Stream.of(
+                parseUrl("http://[email protected]/path?query=1#Ref";)
+                        .part("HOST", "flink.apache.org")
+                        .part("PATH", "/path")
+                        .part("QUERY", "query=1")
+                        .part("REF", "Ref")
+                        .part("PROTOCOL", "http")
+                        .part("FILE", "/path?query=1")
+                        .part("AUTHORITY", "[email protected]")
+                        .part("USERINFO", "userinfo")
+                        .queryParam("query", "1")
+                        .toSpec(),
+                parseUrl(
+                                
"https://use%20r:pas%[email protected]/dir%20/pa%20th.HTML?query=x%20y&q2=2#Ref%20two";)
+                        .part("HOST", "example.com")
+                        .part("PATH", "/dir%20/pa%20th.HTML")
+                        .part("QUERY", "query=x%20y&q2=2")
+                        .part("REF", "Ref%20two")
+                        .part("PROTOCOL", "https")
+                        .part("FILE", "/dir%20/pa%20th.HTML?query=x%20y&q2=2")
+                        .part("AUTHORITY", "use%20r:pas%[email protected]")
+                        .part("USERINFO", "use%20r:pas%20s")
+                        .queryParam("query", "x%20y")
+                        .queryParam("q2", "2")
+                        .toSpec(),
+                parseUrl("http://user:pass@host";)
+                        .part("HOST", "host")
+                        .part("PATH", "")
+                        .part("QUERY", null)
+                        .part("REF", null)
+                        .part("PROTOCOL", "http")
+                        .part("FILE", "")
+                        .part("AUTHORITY", "user:pass@host")
+                        .part("USERINFO", "user:pass")
+                        .queryParam("query", null)
+                        .toSpec(),
+                parseUrl("http://user:pass@host/";)
+                        .part("HOST", "host")
+                        .part("PATH", "/")
+                        .part("QUERY", null)
+                        .part("REF", null)
+                        .part("PROTOCOL", "http")
+                        .part("FILE", "/")
+                        .part("AUTHORITY", "user:pass@host")
+                        .part("USERINFO", "user:pass")
+                        .queryParam("query", null)
+                        .toSpec(),
+                parseUrl("http://user:pass@host/?#";)
+                        .part("HOST", "host")
+                        .part("PATH", "/")
+                        .part("QUERY", "")
+                        .part("REF", "")
+                        .part("PROTOCOL", "http")
+                        .part("FILE", "/?")
+                        .part("AUTHORITY", "user:pass@host")
+                        .part("USERINFO", "user:pass")
+                        .queryParam("query", null)
+                        .toSpec(),
+                parseUrl("http://user:pass@host/file;param?query;p2";)
+                        .part("HOST", "host")
+                        .part("PATH", "/file;param")
+                        .part("QUERY", "query;p2")
+                        .part("REF", null)
+                        .part("PROTOCOL", "http")
+                        .part("FILE", "/file;param?query;p2")
+                        .part("AUTHORITY", "user:pass@host")
+                        .part("USERINFO", "user:pass")
+                        .queryParam("query", null)
+                        .toSpec(),
+                parseUrl("invalid://user:pass@host/file;param?query;p2")
+                        .part("HOST", null)
+                        .part("PATH", null)
+                        .part("QUERY", null)
+                        .part("REF", null)
+                        .part("PROTOCOL", null)
+                        .part("FILE", null)
+                        .part("AUTHORITY", null)
+                        .part("USERINFO", null)
+                        .queryParam("query", null)
+                        .toSpec());
+    }
+
+    private ParseUrlCases parseUrl(String url) {
+        return new ParseUrlCases(url);
+    }
+
+    /** Fluent builder for PARSE_URL specs: one self-describing line per 
extracted URL part. */
+    private static final class ParseUrlCases {
+        private TestSetSpec spec;
+
+        ParseUrlCases(String url) {
+            spec =
+                    
TestSetSpec.forFunction(BuiltInFunctionDefinitions.PARSE_URL, url)
+                            .onFieldsWithData(url)
+                            .andDataTypes(DataTypes.STRING());
+        }
+
+        ParseUrlCases part(String part, String expected) {
+            spec =
+                    spec.testResult(
+                            $("f0").parseUrl(part),
+                            "PARSE_URL(f0, '" + part + "')",
+                            expected,
+                            DataTypes.STRING());
+            return this;
+        }
+
+        ParseUrlCases queryParam(String key, String expected) {
+            spec =
+                    spec.testResult(
+                            $("f0").parseUrl("QUERY", key),
+                            "PARSE_URL(f0, 'QUERY', '" + key + "')",
+                            expected,
+                            DataTypes.STRING());
+            return this;
+        }
+
+        TestSetSpec toSpec() {
+            return spec;
+        }
+    }
+
+    private Stream<TestSetSpec> substringTestCases() {
+        return Stream.of(
+                TestSetSpec.forFunction(BuiltInFunctionDefinitions.SUBSTRING)
+                        .onFieldsWithData("This is a test String.", 3, -3, 1, 
"1世3", null)
+                        .andDataTypes(
+                                DataTypes.STRING(),
+                                DataTypes.INT(),
+                                DataTypes.INT(),
+                                DataTypes.INT(),
+                                DataTypes.STRING(),
+                                DataTypes.STRING())
+                        // two-arg form
+                        .testResult(
+                                $("f0").substring(2),
+                                "SUBSTRING(f0, 2)",
+                                "his is a test String.",
+                                DataTypes.STRING())
+                        // three-arg form
+                        .testResult(
+                                $("f0").substring(2, 5),
+                                "SUBSTRING(f0, 2, 5)",
+                                "his i",
+                                DataTypes.STRING())
+                        .testResult(
+                                $("f0").substring(2, 3),
+                                "SUBSTRING(f0, 2, 3)",
+                                "his",
+                                DataTypes.STRING())
+                        // start/length from fields
+                        .testResult(
+                                $("f0").substring(1, $("f1")),
+                                "SUBSTRING(f0, 1, f1)",
+                                "Thi",
+                                DataTypes.STRING())
+                        .testResult(
+                                $("f0").substring($("f3"), $("f1")),
+                                "SUBSTRING(f0, f3, f1)",
+                                "Thi",
+                                DataTypes.STRING())
+                        // start with implicit cast from TINYINT
+                        .testResult(
+                                
$("f0").substring(lit(1).cast(DataTypes.TINYINT()), $("f1")),
+                                "SUBSTRING(f0, CAST(1 AS TINYINT), f1)",
+                                "Thi",
+                                DataTypes.STRING())
+                        // multibyte characters counted by code point
+                        .testResult(
+                                $("f4").substring(1, 2),
+                                "SUBSTRING(f4, 1, 2)",
+                                "1世",
+                                DataTypes.STRING())
+                        // length past the end is clamped
+                        .testSqlResult(
+                                "SUBSTRING(f0, 2, 100)",
+                                "his is a test String.",
+                                DataTypes.STRING())
+                        // start past the end yields empty
+                        .testSqlResult("SUBSTRING(f0, 100, 10)", "", 
DataTypes.STRING())
+                        // negative length yields null
+                        .testSqlResult("SUBSTRING(f0, 2, -1)", null, 
DataTypes.STRING())
+                        .testSqlResult("SUBSTRING(f0, 2, f2)", null, 
DataTypes.STRING())
+                        // null input yields null
+                        .testSqlResult("SUBSTRING(f5, 2, 3)", null, 
DataTypes.STRING())
+                        .testSqlResult(
+                                "SUBSTRING(CAST(NULL AS VARCHAR), 2, 3)", 
null, DataTypes.STRING())
+                        // SQL FROM/FOR syntax
+                        .testSqlResult("SUBSTRING(f0 FROM 2 FOR 1)", "h", 
DataTypes.STRING())
+                        .testSqlResult(
+                                "SUBSTRING(f0 FROM 2)", "his is a test 
String.", DataTypes.STRING())
+                        .testSqlResult("SUBSTRING(f0 FROM -2)", "g.", 
DataTypes.STRING())
+                        .testSqlResult("SUBSTRING(f0 FROM -2 FOR 1)", "g", 
DataTypes.STRING())
+                        .testSqlResult("SUBSTRING(f0 FROM -2 FOR 0)", "", 
DataTypes.STRING()));
+    }
+
+    private Stream<TestSetSpec> substrTestCases() {
+        return Stream.of(
+                TestSetSpec.forFunction(BuiltInFunctionDefinitions.SUBSTR)
+                        .onFieldsWithData("This is a test String.", 3, -3, 1, 
"1世3", null)
+                        .andDataTypes(
+                                DataTypes.STRING(),
+                                DataTypes.INT(),
+                                DataTypes.INT(),
+                                DataTypes.INT(),
+                                DataTypes.STRING(),
+                                DataTypes.STRING())
+                        .testResult(
+                                $("f0").substr(2, 3), "SUBSTR(f0, 2, 3)", 
"his", DataTypes.STRING())
+                        .testResult(
+                                $("f0").substr(2),
+                                "SUBSTR(f0, 2)",
+                                "his is a test String.",
+                                DataTypes.STRING())
+                        .testSqlResult(
+                                "SUBSTR(f0, 2, 100)", "his is a test String.", 
DataTypes.STRING())
+                        .testSqlResult("SUBSTR(f0, 100, 10)", "", 
DataTypes.STRING())
+                        // negative length yields null
+                        .testSqlResult("SUBSTR(f0, 2, -1)", null, 
DataTypes.STRING())
+                        .testSqlResult("SUBSTR(f0, 2, f2)", null, 
DataTypes.STRING())
+                        // null input yields null
+                        .testSqlResult("SUBSTR(f5, 2, 3)", null, 
DataTypes.STRING())
+                        .testSqlResult(
+                                "SUBSTR(CAST(NULL AS VARCHAR), 2, 3)", null, 
DataTypes.STRING())
+                        .testSqlResult("SUBSTR(f0, f3, f1)", "Thi", 
DataTypes.STRING())
+                        // multibyte characters counted by code point
+                        .testSqlResult("SUBSTR(f4, 1, 2)", "1世", 
DataTypes.STRING()));
+    }
 }
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 bede804aa8b..f92847ee3a6 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
@@ -240,30 +240,6 @@ class ScalarFunctionsTest extends ScalarTypesTestBase {
     )
   }
 
-  @Test
-  def testSubstring(): Unit = {
-    testAllApis('f0.substring(2), "SUBSTRING(f0, 2)", "his is a test String.")
-
-    testAllApis('f0.substring(2, 5), "SUBSTRING(f0, 2, 5)", "his i")
-
-    testAllApis('f0.substring(1, 'f7), "SUBSTRING(f0, 1, f7)", "Thi")
-
-    testAllApis(
-      'f0.substring(1.cast(DataTypes.TINYINT), 'f7),
-      "SUBSTRING(f0, CAST(1 AS TINYINT), f7)",
-      "Thi")
-
-    testSqlApi("SUBSTRING(f0 FROM 2 FOR 1)", "h")
-
-    testSqlApi("SUBSTRING(f0 FROM 2)", "his is a test String.")
-
-    testSqlApi("SUBSTRING(f0 FROM -2)", "g.")
-
-    testSqlApi("SUBSTRING(f0 FROM -2 FOR 1)", "g")
-
-    testSqlApi("SUBSTRING(f0 FROM -2 FOR 0)", "")
-  }
-
   @Test
   def testReplace(): Unit = {
     testAllApis('f0.replace(" ", "_"), "REPLACE(f0, ' ', '_')", 
"This_is_a_test_String.")
@@ -822,23 +798,6 @@ class ScalarFunctionsTest extends ScalarTypesTestBase {
     testSqlApi("to_base64(from_base64(f38))", "AQIDBA==")
   }
 
-  @Test
-  def testSubString(): Unit = {
-    Array("substring", "substr").foreach {
-      substr =>
-        testAllApis('f0.substr(2, 3), s"$substr(f0, 2, 3)", "his")
-        testAllApis('f0.substr(2), s"$substr(f0, 2)", "his is a test String.")
-        testSqlApi(s"$substr(f0, 2, 100)", "his is a test String.")
-        testSqlApi(s"$substr(f0, 100, 10)", "")
-        testSqlApi(s"$substr(f0, 2, -1)", "NULL")
-        testSqlApi(s"$substr(f40, 2, 3)", "NULL")
-        testSqlApi(s"$substr(CAST(null AS VARCHAR), 2, 3)", "NULL")
-        testSqlApi(s"$substr(f0, 2, f14)", "NULL")
-        testSqlApi(s"$substr(f0, f30, f7)", "Thi")
-        testSqlApi(s"$substr(f39, 1, 2)", "1世")
-    }
-  }
-
   @Test
   def testLPad(): Unit = {
     testSqlApi("lpad(f33,1,'??')", "NULL")
@@ -889,127 +848,6 @@ class ScalarFunctionsTest extends ScalarTypesTestBase {
     testAllApis("äää".rpad(13, "12345"), "rpad('äää',13,'12345')", 
"äää1234512345")
   }
 
-  @Test
-  def testParseUrl(): Unit = {
-
-    // NOTE: parse_url() requires HOST PATH etc. all capitalized
-    def testUrl(
-        url: String,
-        host: String,
-        path: String,
-        query: String,
-        ref: String,
-        protocol: String,
-        file: String,
-        authority: String,
-        userInfo: String,
-        qv: String): Unit = {
-
-      val parts =
-        Map(
-          "HOST" -> host,
-          "PATH" -> path,
-          "QUERY" -> query,
-          "REF" -> ref,
-          "PROTOCOL" -> protocol,
-          "FILE" -> file,
-          "AUTHORITY" -> authority,
-          "USERINFO" -> userInfo)
-
-      for ((n, v) <- parts) {
-        testAllApis(url.parseUrl(s"$n"), s"parse_url('$url', '$n')", v)
-      }
-
-      testAllApis(url.parseUrl("QUERY", "query"), s"parse_url('$url', 'QUERY', 
'query')", qv)
-    }
-
-    testUrl(
-      "http://[email protected]/path?query=1#Ref";,
-      "flink.apache.org",
-      "/path",
-      "query=1",
-      "Ref",
-      "http",
-      "/path?query=1",
-      "[email protected]",
-      "userinfo",
-      "1"
-    )
-
-    testUrl(
-      
"https://use%20r:pas%[email protected]/dir%20/pa%20th.HTML?query=x%20y&q2=2#Ref%20two";,
-      "example.com",
-      "/dir%20/pa%20th.HTML",
-      "query=x%20y&q2=2",
-      "Ref%20two",
-      "https",
-      "/dir%20/pa%20th.HTML?query=x%20y&q2=2",
-      "use%20r:pas%[email protected]",
-      "use%20r:pas%20s",
-      "x%20y"
-    )
-
-    testUrl(
-      "http://user:pass@host";,
-      "host",
-      "",
-      "NULL",
-      "NULL",
-      "http",
-      "",
-      "user:pass@host",
-      "user:pass",
-      "NULL")
-
-    testUrl(
-      "http://user:pass@host/";,
-      "host",
-      "/",
-      "NULL",
-      "NULL",
-      "http",
-      "/",
-      "user:pass@host",
-      "user:pass",
-      "NULL")
-
-    testUrl(
-      "http://user:pass@host/?#";,
-      "host",
-      "/",
-      "",
-      "",
-      "http",
-      "/?",
-      "user:pass@host",
-      "user:pass",
-      "NULL")
-
-    testUrl(
-      "http://user:pass@host/file;param?query;p2";,
-      "host",
-      "/file;param",
-      "query;p2",
-      "NULL",
-      "http",
-      "/file;param?query;p2",
-      "user:pass@host",
-      "user:pass",
-      "NULL")
-
-    testUrl(
-      "invalid://user:pass@host/file;param?query;p2",
-      "NULL",
-      "NULL",
-      "NULL",
-      "NULL",
-      "NULL",
-      "NULL",
-      "NULL",
-      "NULL",
-      "NULL")
-  }
-
   @Test
   def testRepeat(): Unit = {
     testAllApis('f0.repeat(1), "REPEAT(f0, 1)", "This is a test String.")
diff --git 
a/flink-table/flink-table-runtime/src/main/java/org/apache/flink/table/runtime/functions/SqlFunctionUtils.java
 
b/flink-table/flink-table-runtime/src/main/java/org/apache/flink/table/runtime/functions/SqlFunctionUtils.java
index 54c45f0a4f1..58dfbaf10b0 100644
--- 
a/flink-table/flink-table-runtime/src/main/java/org/apache/flink/table/runtime/functions/SqlFunctionUtils.java
+++ 
b/flink-table/flink-table-runtime/src/main/java/org/apache/flink/table/runtime/functions/SqlFunctionUtils.java
@@ -603,7 +603,6 @@ public class SqlFunctionUtils {
         try {
             url = URL_CACHE.get(urlStr);
         } catch (Exception e) {
-            LOG.error("Parse URL error: " + urlStr, e);
             return null;
         }
         if ("HOST".equals(partToExtract)) {
@@ -666,16 +665,9 @@ public class SqlFunctionUtils {
 
     public static String subString(String str, long start, long len) {
         if (len < 0) {
-            LOG.error(
-                    "len of 'substring(str, start, len)' must be >= 0 and Int 
type, but len = {}",
-                    len);
             return null;
         }
         if (len > Integer.MAX_VALUE || start > Integer.MAX_VALUE) {
-            LOG.error(
-                    "len or start of 'substring(str, start, len)' must be Int 
type, but len = {}, start = {}",
-                    len,
-                    start);
             return null;
         }
         int length = (int) len;

Reply via email to