lincoln-lil commented on code in PR #25122:
URL: https://github.com/apache/flink/pull/25122#discussion_r1700318289


##########
flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/StringFunctionsITCase.java:
##########
@@ -25,12 +25,17 @@
 
 import static org.apache.flink.table.api.Expressions.$;
 import static org.apache.flink.table.api.Expressions.call;
+import static org.apache.flink.table.api.Expressions.lit;
 
 /** Test String functions correct behaviour. */
 class StringFunctionsITCase extends BuiltInFunctionTestBase {
 
     @Override
     Stream<TestSetSpec> getTestSetSpecs() {
+        return Stream.of(regexpExtractTestCases(), 
translateTestCases()).flatMap(s -> s);

Review Comment:
   nit: can be simplified to `Stream.concat(regexpExtractTestCases(), 
translateTestCases());`



##########
flink-table/flink-table-runtime/src/main/java/org/apache/flink/table/runtime/functions/scalar/TranslateFunction.java:
##########
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+package org.apache.flink.table.runtime.functions.scalar;
+
+import org.apache.flink.annotation.Internal;
+import org.apache.flink.table.data.StringData;
+import org.apache.flink.table.data.binary.BinaryStringData;
+import org.apache.flink.table.data.binary.BinaryStringDataUtil;
+import org.apache.flink.table.functions.BuiltInFunctionDefinitions;
+import org.apache.flink.table.functions.SpecializedFunction.SpecializedContext;
+import org.apache.flink.table.utils.ThreadLocalCache;
+
+import org.apache.commons.lang3.tuple.Pair;
+
+import javax.annotation.Nullable;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/** Implementation of {@link BuiltInFunctionDefinitions#TRANSLATE}. */
+@Internal
+public class TranslateFunction extends BuiltInScalarFunction {
+
+    private static final ThreadLocalCache<Pair<String, String>, Map<Integer, 
String>> DICT_CACHE =
+            new ThreadLocalCache<Pair<String, String>, Map<Integer, String>>() 
{
+                @Override
+                public Map<Integer, String> getNewInstance(Pair<String, 
String> key) {
+                    return buildDict(key.getLeft(), key.getRight());
+                }
+            };
+
+    public TranslateFunction(SpecializedContext context) {
+        super(BuiltInFunctionDefinitions.TRANSLATE, context);
+    }
+
+    public @Nullable StringData eval(
+            @Nullable StringData expr, @Nullable StringData fromStr, @Nullable 
StringData toStr) {
+        if (expr == null
+                || fromStr == null
+                || BinaryStringDataUtil.isEmpty((BinaryStringData) expr)
+                || BinaryStringDataUtil.isEmpty((BinaryStringData) fromStr)) {
+            return expr;
+        }
+
+        final String source = expr.toString();
+        final String from = fromStr.toString();
+        final String to = toStr == null ? "" : toStr.toString();
+
+        Map<Integer, String> dict = DICT_CACHE.get(Pair.of(from, to));
+
+        return BinaryStringData.fromString(translate(source, dict));
+    }
+
+    private String translate(String expr, Map<Integer, String> dict) {
+        StringBuilder res = new StringBuilder();
+        for (int i = 0; i < expr.length(); ) {
+            int codePoint = expr.codePointAt(i);

Review Comment:
   This makes me thought of potential bugs which use `charAt` instead among 
other functions, can you test existing string functions(e.g., split function) 
with supplementary character?(This can be a separate issue)



##########
flink-table/flink-table-runtime/src/main/java/org/apache/flink/table/runtime/functions/scalar/TranslateFunction.java:
##########
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+package org.apache.flink.table.runtime.functions.scalar;
+
+import org.apache.flink.annotation.Internal;
+import org.apache.flink.table.data.StringData;
+import org.apache.flink.table.data.binary.BinaryStringData;
+import org.apache.flink.table.data.binary.BinaryStringDataUtil;
+import org.apache.flink.table.functions.BuiltInFunctionDefinitions;
+import org.apache.flink.table.functions.SpecializedFunction.SpecializedContext;
+import org.apache.flink.table.utils.ThreadLocalCache;
+
+import org.apache.commons.lang3.tuple.Pair;
+
+import javax.annotation.Nullable;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/** Implementation of {@link BuiltInFunctionDefinitions#TRANSLATE}. */
+@Internal
+public class TranslateFunction extends BuiltInScalarFunction {
+
+    private static final ThreadLocalCache<Pair<String, String>, Map<Integer, 
String>> DICT_CACHE =
+            new ThreadLocalCache<Pair<String, String>, Map<Integer, String>>() 
{
+                @Override
+                public Map<Integer, String> getNewInstance(Pair<String, 
String> key) {
+                    return buildDict(key.getLeft(), key.getRight());
+                }
+            };
+
+    public TranslateFunction(SpecializedContext context) {
+        super(BuiltInFunctionDefinitions.TRANSLATE, context);
+    }
+
+    public @Nullable StringData eval(
+            @Nullable StringData expr, @Nullable StringData fromStr, @Nullable 
StringData toStr) {
+        if (expr == null
+                || fromStr == null
+                || BinaryStringDataUtil.isEmpty((BinaryStringData) expr)
+                || BinaryStringDataUtil.isEmpty((BinaryStringData) fromStr)) {
+            return expr;
+        }
+
+        final String source = expr.toString();
+        final String from = fromStr.toString();
+        final String to = toStr == null ? "" : toStr.toString();
+
+        Map<Integer, String> dict = DICT_CACHE.get(Pair.of(from, to));
+
+        return BinaryStringData.fromString(translate(source, dict));
+    }
+
+    private String translate(String expr, Map<Integer, String> dict) {
+        StringBuilder res = new StringBuilder();
+        for (int i = 0; i < expr.length(); ) {
+            int codePoint = expr.codePointAt(i);
+            int charCount = Character.charCount(codePoint);

Review Comment:
   Declares `charCount` before loop, then move `i += charCount` inside the loop 
condition and  use plus expression `res.append(expr, i, i + charCount);` may 
looks more consistent?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to