diff --git a/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/schema/function/BuildInSqlFunctionTable.java b/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/schema/function/BuildInSqlFunctionTable.java index 47addc84a..9ef8fd9c3 100644 --- a/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/schema/function/BuildInSqlFunctionTable.java +++ b/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/schema/function/BuildInSqlFunctionTable.java @@ -109,9 +109,11 @@ import org.apache.geaflow.dsl.udf.table.string.Instr; import org.apache.geaflow.dsl.udf.table.string.IsBlank; import org.apache.geaflow.dsl.udf.table.string.KeyValue; +import org.apache.geaflow.dsl.udf.table.string.LPad; import org.apache.geaflow.dsl.udf.table.string.LTrim; import org.apache.geaflow.dsl.udf.table.string.Length; import org.apache.geaflow.dsl.udf.table.string.Like; +import org.apache.geaflow.dsl.udf.table.string.RPad; import org.apache.geaflow.dsl.udf.table.string.RTrim; import org.apache.geaflow.dsl.udf.table.string.RegExp; import org.apache.geaflow.dsl.udf.table.string.RegExpExtract; @@ -123,6 +125,7 @@ import org.apache.geaflow.dsl.udf.table.string.Space; import org.apache.geaflow.dsl.udf.table.string.SplitEx; import org.apache.geaflow.dsl.udf.table.string.Substr; +import org.apache.geaflow.dsl.udf.table.string.Trim; import org.apache.geaflow.dsl.udf.table.string.UrlDecode; import org.apache.geaflow.dsl.udf.table.string.UrlEncode; import org.apache.geaflow.dsl.util.FunctionUtil; @@ -186,6 +189,7 @@ public class BuildInSqlFunctionTable extends ListSqlOperatorTable { .add(GeaFlowFunction.of(KeyValue.class)) .add(GeaFlowFunction.of(Length.class)) .add(GeaFlowFunction.of(Like.class)) + .add(GeaFlowFunction.of(LPad.class)) .add(GeaFlowFunction.of(LTrim.class)) .add(GeaFlowFunction.of(RegExp.class)) .add(GeaFlowFunction.of(RegexpCount.class)) @@ -194,10 +198,12 @@ public class BuildInSqlFunctionTable extends ListSqlOperatorTable { .add(GeaFlowFunction.of(Repeat.class)) .add(GeaFlowFunction.of(Replace.class)) .add(GeaFlowFunction.of(Reverse.class)) + .add(GeaFlowFunction.of(RPad.class)) .add(GeaFlowFunction.of(RTrim.class)) .add(GeaFlowFunction.of(Space.class)) .add(GeaFlowFunction.of(SplitEx.class)) .add(GeaFlowFunction.of(Substr.class)) + .add(GeaFlowFunction.of(Trim.class)) .add(GeaFlowFunction.of(UrlDecode.class)) .add(GeaFlowFunction.of(UrlEncode.class)) .add(GeaFlowFunction.of(GetJsonObject.class)) diff --git a/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/udf/table/string/LPad.java b/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/udf/table/string/LPad.java new file mode 100644 index 000000000..53afc6641 --- /dev/null +++ b/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/udf/table/string/LPad.java @@ -0,0 +1,51 @@ +/* + * 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.geaflow.dsl.udf.table.string; + +import org.apache.geaflow.dsl.common.function.Description; +import org.apache.geaflow.dsl.common.function.UDF; + +@Description(name = "lpad", description = "Returns the string left-padded to the given length " + + "with the specified pad string.") +public class LPad extends UDF { + + public String eval(String str, Integer len, String pad) { + if (str == null || len == null || pad == null) { + return null; + } + if (len <= 0) { + return ""; + } + if (len <= str.length()) { + return str.substring(0, len); + } + if (pad.isEmpty()) { + return str; + } + StringBuilder sb = new StringBuilder(); + int padLen = len - str.length(); + while (sb.length() < padLen) { + sb.append(pad); + } + sb.setLength(padLen); + sb.append(str); + return sb.toString(); + } +} \ No newline at end of file diff --git a/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/udf/table/string/RPad.java b/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/udf/table/string/RPad.java new file mode 100644 index 000000000..18476ae3f --- /dev/null +++ b/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/udf/table/string/RPad.java @@ -0,0 +1,50 @@ +/* + * 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.geaflow.dsl.udf.table.string; + +import org.apache.geaflow.dsl.common.function.Description; +import org.apache.geaflow.dsl.common.function.UDF; + +@Description(name = "rpad", description = "Returns the string right-padded to the given length " + + "with the specified pad string.") +public class RPad extends UDF { + + public String eval(String str, Integer len, String pad) { + if (str == null || len == null || pad == null) { + return null; + } + if (len <= 0) { + return ""; + } + if (len <= str.length()) { + return str.substring(0, len); + } + if (pad.isEmpty()) { + return str; + } + StringBuilder sb = new StringBuilder(); + sb.append(str); + while (sb.length() < len) { + sb.append(pad); + } + sb.setLength(len); + return sb.toString(); + } +} \ No newline at end of file diff --git a/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/udf/table/string/Trim.java b/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/udf/table/string/Trim.java new file mode 100644 index 000000000..ba37fa91e --- /dev/null +++ b/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/udf/table/string/Trim.java @@ -0,0 +1,51 @@ +/* + * 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.geaflow.dsl.udf.table.string; + +import org.apache.commons.lang3.StringUtils; +import org.apache.geaflow.common.binary.BinaryString; +import org.apache.geaflow.dsl.common.function.Description; +import org.apache.geaflow.dsl.common.function.UDF; + +@Description(name = "trim", description = "Returns a string with both leading and trailing whitespace removed.") +public class Trim extends UDF { + + public String eval(String s) { + if (s == null) { + return null; + } + return StringUtils.strip(s); + } + + public BinaryString eval(BinaryString s) { + if (s == null) { + return null; + } + int l = 0; + int r = s.getLength() - 1; + while (l <= r && s.getByte(l) == ' ') { + l++; + } + while (r >= l && s.getByte(r) == ' ') { + r--; + } + return s.substring(l, r + 1); + } +} \ No newline at end of file diff --git a/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/java/org/apache/geaflow/dsl/runtime/query/StringFunctionTest.java b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/java/org/apache/geaflow/dsl/runtime/query/StringFunctionTest.java new file mode 100644 index 000000000..4843b145a --- /dev/null +++ b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/java/org/apache/geaflow/dsl/runtime/query/StringFunctionTest.java @@ -0,0 +1,52 @@ +/* + * 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.geaflow.dsl.runtime.query; + +import org.testng.annotations.Test; + +public class StringFunctionTest { + + @Test + public void testTrim() throws Exception { + QueryTester + .build() + .withQueryPath("/query/function_trim.sql") + .execute() + .checkSinkResult(); + } + + @Test + public void testLpad() throws Exception { + QueryTester + .build() + .withQueryPath("/query/function_lpad.sql") + .execute() + .checkSinkResult(); + } + + @Test + public void testRpad() throws Exception { + QueryTester + .build() + .withQueryPath("/query/function_rpad.sql") + .execute() + .checkSinkResult(); + } +} \ No newline at end of file diff --git a/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/expect/function_lpad.txt b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/expect/function_lpad.txt new file mode 100644 index 000000000..af9947bab --- /dev/null +++ b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/expect/function_lpad.txt @@ -0,0 +1 @@ +xxxhi,hello,hel,ababahi \ No newline at end of file diff --git a/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/expect/function_rpad.txt b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/expect/function_rpad.txt new file mode 100644 index 000000000..d5d5389c0 --- /dev/null +++ b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/expect/function_rpad.txt @@ -0,0 +1 @@ +hixxx,hello,hel,hiababa \ No newline at end of file diff --git a/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/expect/function_trim.txt b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/expect/function_trim.txt new file mode 100644 index 000000000..77a3dd2b3 --- /dev/null +++ b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/expect/function_trim.txt @@ -0,0 +1 @@ +hello,world,a b c \ No newline at end of file diff --git a/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/query/function_lpad.sql b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/query/function_lpad.sql new file mode 100644 index 000000000..209864d9f --- /dev/null +++ b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/query/function_lpad.sql @@ -0,0 +1,35 @@ +/* + * 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. + */ + +CREATE TABLE output_console( + c1 varchar, + c2 varchar, + c3 varchar, + c4 varchar +) WITH ( + type='file', + geaflow.dsl.file.path='${target}' +); + +INSERT INTO output_console +SELECT + lpad('hi', 5, 'x'), + lpad('hello', 5, 'x'), + lpad('hello', 3, 'x'), + lpad('hi', 7, 'ab') \ No newline at end of file diff --git a/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/query/function_rpad.sql b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/query/function_rpad.sql new file mode 100644 index 000000000..25e43f069 --- /dev/null +++ b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/query/function_rpad.sql @@ -0,0 +1,35 @@ +/* + * 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. + */ + +CREATE TABLE output_console( + c1 varchar, + c2 varchar, + c3 varchar, + c4 varchar +) WITH ( + type='file', + geaflow.dsl.file.path='${target}' +); + +INSERT INTO output_console +SELECT + rpad('hi', 5, 'x'), + rpad('hello', 5, 'x'), + rpad('hello', 3, 'x'), + rpad('hi', 7, 'ab') \ No newline at end of file diff --git a/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/query/function_trim.sql b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/query/function_trim.sql new file mode 100644 index 000000000..74020d299 --- /dev/null +++ b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/query/function_trim.sql @@ -0,0 +1,33 @@ +/* + * 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. + */ + +CREATE TABLE output_console( + c1 varchar, + c2 varchar, + c3 varchar +) WITH ( + type='file', + geaflow.dsl.file.path='${target}' +); + +INSERT INTO output_console +SELECT + trim(' hello '), + trim('world'), + trim(' a b c ') \ No newline at end of file