From 3cff53ecb16df948b69e20970332620a9dfdcdb0 Mon Sep 17 00:00:00 2001 From: emptyOVO Date: Fri, 27 Dec 2024 14:47:13 +0800 Subject: [PATCH] [INLONG-11002][SDK] Transform SQL support Fibonacci function --- .../arithmetic/FibonacciFunction.java | 77 +++++++++++++++++++ .../arithmetic/TestFibonacciFunction.java | 62 +++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/process/function/arithmetic/FibonacciFunction.java create mode 100644 inlong-sdk/transform-sdk/src/test/java/org/apache/inlong/sdk/transform/process/function/arithmetic/TestFibonacciFunction.java diff --git a/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/process/function/arithmetic/FibonacciFunction.java b/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/process/function/arithmetic/FibonacciFunction.java new file mode 100644 index 0000000000..e05ed1d066 --- /dev/null +++ b/inlong-sdk/transform-sdk/src/main/java/org/apache/inlong/sdk/transform/process/function/arithmetic/FibonacciFunction.java @@ -0,0 +1,77 @@ +/* + * 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.arithmetic; + +import org.apache.inlong.sdk.transform.decode.SourceData; +import org.apache.inlong.sdk.transform.process.Context; +import org.apache.inlong.sdk.transform.process.function.FunctionConstant; +import org.apache.inlong.sdk.transform.process.function.TransformFunction; +import org.apache.inlong.sdk.transform.process.operator.OperatorTools; +import org.apache.inlong.sdk.transform.process.parser.ValueParser; + +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.Function; + +import java.math.BigDecimal; +import java.util.List; + +/** + * FibonacciFunction -> fibonacci(numeric) + * Description: + * - Return NULL if 'numeric' is NULL; + * - Returns the nth Fibonacci number + */ +@TransformFunction(type = FunctionConstant.ARITHMETIC_TYPE, names = { + "fibonacci"}, parameter = "(Numeric numeric)", descriptions = { + "- Return NULL if 'numeric' is NULL;", + "- Returns the nth Fibonacci number" + }, examples = {"fibonacci(0) = 0", "fibonacci(1) = 1", "fibonacci(2) = 1", "fibonacci(3) = 2", + "fibonacci(4) = 3"}) +public class FibonacciFunction implements ValueParser { + + private ValueParser numberParser; + + public FibonacciFunction(Function expr) { + if (expr.getParameters() != null) { + List expressions = expr.getParameters().getExpressions(); + if (expressions != null && expressions.size() == 1) { + numberParser = OperatorTools.buildParser(expressions.get(0)); + } + } + } + + @Override + public Object parse(SourceData sourceData, int rowIndex, Context context) { + Object numberObj = numberParser.parse(sourceData, rowIndex, context); + BigDecimal numberValue = OperatorTools.parseBigDecimal(numberObj); + return fibonacci(numberValue.intValue()); + } + + private long fibonacci(int n) { + if (n <= 1) { + return n; + } + long prev = 0, curr = 1; + for (int i = 2; i <= n; i++) { + long temp = curr; + curr = curr + prev; + prev = temp; + } + return curr; + } +} diff --git a/inlong-sdk/transform-sdk/src/test/java/org/apache/inlong/sdk/transform/process/function/arithmetic/TestFibonacciFunction.java b/inlong-sdk/transform-sdk/src/test/java/org/apache/inlong/sdk/transform/process/function/arithmetic/TestFibonacciFunction.java new file mode 100644 index 0000000000..abd31847b7 --- /dev/null +++ b/inlong-sdk/transform-sdk/src/test/java/org/apache/inlong/sdk/transform/process/function/arithmetic/TestFibonacciFunction.java @@ -0,0 +1,62 @@ +/* + * 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.arithmetic; + +import org.apache.inlong.sdk.transform.decode.SourceDecoderFactory; +import org.apache.inlong.sdk.transform.encode.SinkEncoderFactory; +import org.apache.inlong.sdk.transform.pojo.TransformConfig; +import org.apache.inlong.sdk.transform.process.TransformProcessor; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.List; + +public class TestFibonacciFunction extends AbstractFunctionArithmeticTestBase { + + @Test + public void testFibonacciFunction() throws Exception { + String transformSql = "select fibonacci(numeric1) from source"; + TransformConfig config = new TransformConfig(transformSql); + TransformProcessor processor = TransformProcessor + .create(config, SourceDecoderFactory.createCsvDecoder(csvSource), + SinkEncoderFactory.createKvEncoder(kvSink)); + + // case1: fibonacci(0) + List output1 = processor.transform("0|4|6|8", new HashMap<>()); + Assert.assertEquals(1, output1.size()); + Assert.assertEquals(output1.get(0), "result=0"); + + // case2: fibonacci(1) + List output2 = processor.transform("1|4|6|8", new HashMap<>()); + Assert.assertEquals(1, output2.size()); + Assert.assertEquals(output2.get(0), "result=1"); + + // case3: fibonacci(7) + List output3 = processor.transform("7|4|6|8", new HashMap<>()); + Assert.assertEquals(1, output3.size()); + Assert.assertEquals(output3.get(0), "result=13"); + + // case4: fibonacci(10) + List output4 = processor.transform("10|4|6|8", new HashMap<>()); + Assert.assertEquals(1, output4.size()); + Assert.assertEquals(output4.get(0), "result=55"); + } + +}