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

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


The following commit(s) were added to refs/heads/master by this push:
     new 7aa0247228 [INLONG-10902][SDK] Transform support HEX(numeric or 
string) function (#10904)
7aa0247228 is described below

commit 7aa0247228a4439123e5096dc6ac669ec2167f3f
Author: emptyOVO <118812562+empty...@users.noreply.github.com>
AuthorDate: Sat Aug 31 18:32:45 2024 +0800

    [INLONG-10902][SDK] Transform support HEX(numeric or string) function 
(#10904)
    
    * [INLONG-10902][SDK] Transform support HEX(numeric or string) function
    
    * fix: add functions to check data type
    
    * fix: test data comment
    
    * fix: add anotation
    
    * fix: code conflicts
    
    * fix: add isBigDecimal function to check whether it can be parsed to 
BigDecimal
    
    ---------
    
    Co-authored-by: AloysZhang <aloyszh...@apache.org>
---
 .../transform/process/function/HexFunction.java    | 108 +++++++++++++++++++++
 .../TestTransformArithmeticFunctionsProcessor.java |  29 ++++++
 2 files changed, 137 insertions(+)

diff --git 
a/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/process/function/HexFunction.java
 
b/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/process/function/HexFunction.java
new file mode 100644
index 0000000000..c641209162
--- /dev/null
+++ 
b/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/process/function/HexFunction.java
@@ -0,0 +1,108 @@
+/*
+ * 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.inlong.sdk.transform.process.function;
+
+import org.apache.inlong.sdk.transform.decode.SourceData;
+import org.apache.inlong.sdk.transform.process.Context;
+import org.apache.inlong.sdk.transform.process.operator.OperatorTools;
+import org.apache.inlong.sdk.transform.process.parser.ValueParser;
+
+import net.sf.jsqlparser.expression.Function;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Optional;
+import java.util.regex.Pattern;
+
+/**
+ * HexFunction
+ * description:
+ * - If the input argument is a numeric value (such as an integer), the HEX 
function converts the value to the corresponding hexadecimal string.
+ * - If the input argument is a string, the HEX function converts each 
character in the string to its corresponding hexadecimal ASCII encoding and 
returns the hexadecimal representation of the entire string.
+ */
+@TransformFunction(names = {"hex"})
+class HexFunction implements ValueParser {
+
+    private static final Pattern BIG_DECIMAL_PATTERN = 
Pattern.compile("^[-+]?\\d+(\\.\\d+)?([eE][-+]?\\d+)?$");
+
+    private ValueParser valueParser;
+
+    public HexFunction(Function expr) {
+        valueParser = 
OperatorTools.buildParser(expr.getParameters().getExpressions().get(0));
+    }
+
+    @Override
+    public Object parse(SourceData sourceData, int rowIndex, Context context) {
+        Object valueObj = valueParser.parse(sourceData, rowIndex, context);
+        if (isBigDecimal(valueObj)) {
+            return hex(OperatorTools.parseBigDecimal(valueObj)).toUpperCase();
+        }
+        return hex(OperatorTools.parseString(valueObj)).toUpperCase();
+    }
+
+    private boolean isBigDecimal(Object valueObj) {
+        if (valueObj instanceof BigDecimal) {
+            return true;
+        }
+        if (valueObj instanceof String) {
+            String str = (String) valueObj;
+            return BIG_DECIMAL_PATTERN.matcher(str).matches();
+        }
+        return false;
+    }
+
+    // Handle Integer type
+    private String hex(int number) {
+        return Integer.toHexString(number).toUpperCase();
+    }
+
+    // Handle long type
+    private String hex(long number) {
+        return Long.toHexString(number).toUpperCase();
+    }
+
+    // Handle String type
+    private String hex(String input) {
+        StringBuilder hexString = new StringBuilder();
+        for (char c : input.toCharArray()) {
+            hexString.append(Integer.toHexString((int) c).toUpperCase());
+        }
+        return hexString.toString();
+    }
+
+    // Handle BigDecimal type
+    private String hex(BigDecimal number) {
+        // keep the integer part
+        BigDecimal integerValue = number.setScale(0, RoundingMode.DOWN);
+        return tryConvert(integerValue, BigDecimal::intValueExact, this::hex)
+                // If it cannot convert to integer, try converting to long
+                .orElseGet(() -> tryConvert(integerValue, 
BigDecimal::longValueExact, this::hex)
+                        .orElseThrow(() -> new 
IllegalArgumentException("Number out of range")));
+    }
+
+    // Common conversion and processing methods
+    private <T> Optional<String> tryConvert(BigDecimal number, 
java.util.function.Function<BigDecimal, T> converter,
+            java.util.function.Function<T, String> handler) {
+        try {
+            T value = converter.apply(number);
+            return Optional.ofNullable(handler.apply(value));
+        } catch (ArithmeticException e) {
+            return Optional.empty();
+        }
+    }
+}
diff --git 
a/inlong-sdk/transform-sdk/src/test/java/org/apache/inlong/sdk/transform/process/TestTransformArithmeticFunctionsProcessor.java
 
b/inlong-sdk/transform-sdk/src/test/java/org/apache/inlong/sdk/transform/process/TestTransformArithmeticFunctionsProcessor.java
index 1467636e65..87ce145df6 100644
--- 
a/inlong-sdk/transform-sdk/src/test/java/org/apache/inlong/sdk/transform/process/TestTransformArithmeticFunctionsProcessor.java
+++ 
b/inlong-sdk/transform-sdk/src/test/java/org/apache/inlong/sdk/transform/process/TestTransformArithmeticFunctionsProcessor.java
@@ -619,4 +619,33 @@ public class TestTransformArithmeticFunctionsProcessor {
         Assert.assertTrue(result >= 0.0 && result < 1.0);
     }
 
+    @Test
+    public void testHexFunction() throws Exception {
+        String transformSql1 = "select hex(numeric1) from source";
+        TransformConfig config1 = new TransformConfig(transformSql1);
+        TransformProcessor<String, String> processor1 = TransformProcessor
+                .create(config1, 
SourceDecoderFactory.createCsvDecoder(csvSource),
+                        SinkEncoderFactory.createKvEncoder(kvSink));
+        // case: hex(1007)
+        List<String> output1 = processor1.transform("1007|4|6|8", new 
HashMap<>());
+        Assert.assertEquals(1, output1.size());
+        Assert.assertEquals(output1.get(0), "result=3EF");
+        // case: hex(3.14)
+        List<String> output2 = processor1.transform("3.14|4|6|8", new 
HashMap<>());
+        Assert.assertEquals(1, output2.size());
+        Assert.assertEquals(output2.get(0), "result=3");
+        // case: hex(3.141592653589793)
+        List<String> output3 = processor1.transform("3.141592653589793|4|6|8", 
new HashMap<>());
+        Assert.assertEquals(1, output3.size());
+        Assert.assertEquals(output3.get(0), "result=3");
+        // case: hex(-9223372036854775808)
+        List<String> output4 = 
processor1.transform("-9223372036854775808|4|6|8", new HashMap<>());
+        Assert.assertEquals(1, output4.size());
+        Assert.assertEquals(output4.get(0), "result=8000000000000000");
+        // case: hex(abc)
+        List<String> output5 = processor1.transform("abc|4|6|8", new 
HashMap<>());
+        Assert.assertEquals(1, output5.size());
+        Assert.assertEquals(output5.get(0), "result=616263");
+    }
+
 }

Reply via email to