From 2be0f8fd0efb637fea4fa6100a3f02b69e795f0b Mon Sep 17 00:00:00 2001 From: LiBinfeng <1204975323@qq.com> Date: Tue, 17 Sep 2024 20:12:16 +0800 Subject: [PATCH] [Fix](Nereids) fix append_trailing_char_if_absent function return null --- .../executable/ExecutableFunctions.java | 20 +++-- .../doris/regression/suite/Suite.groovy | 14 +++ .../fold_constant/fold_constant_by_fe.groovy | 86 +++++++++++++++++++ 3 files changed, 114 insertions(+), 6 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/ExecutableFunctions.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/ExecutableFunctions.java index 9bc1bbb71556392..eab5c6f570c7306 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/ExecutableFunctions.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/ExecutableFunctions.java @@ -26,7 +26,9 @@ import org.apache.doris.nereids.trees.expressions.literal.FloatLiteral; import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral; import org.apache.doris.nereids.trees.expressions.literal.LargeIntLiteral; +import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; import org.apache.doris.nereids.trees.expressions.literal.SmallIntLiteral; +import org.apache.doris.nereids.trees.expressions.literal.StringLikeLiteral; import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral; @@ -91,13 +93,19 @@ public static Expression acos(DoubleLiteral literal) { return new DoubleLiteral(Math.acos(literal.getValue())); } - @ExecFunction(name = "append_trailing_if_char_absent", argTypes = {"VARCHAR", "VARCHAR"}, returnType = "VARCHAR") - public static Expression appendTrailingIfCharAbsent(VarcharLiteral literal, VarcharLiteral chr) { - if (literal.getValue().length() != 1) { - return null; + /** + * append_trailing_char_if_absent function + */ + @ExecFunction(name = "append_trailing_char_if_absent", argTypes = {"VARCHAR", "VARCHAR"}, returnType = "VARCHAR") + public static Expression appendTrailingIfCharAbsent(StringLikeLiteral literal, StringLikeLiteral chr) { + if (chr.getStringValue().length() != 1) { + return new NullLiteral(literal.getDataType()); + } + if (literal.getStringValue().endsWith(chr.getStringValue())) { + return literal; + } else { + return new VarcharLiteral(literal.getStringValue() + chr.getStringValue()); } - return literal.getValue().endsWith(chr.getValue()) ? literal - : new VarcharLiteral(literal.getValue() + chr.getValue()); } @ExecFunction(name = "e", argTypes = {}, returnType = "DOUBLE") diff --git a/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy b/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy index 9a14346af10bd86..1eeb2f81b41e472 100644 --- a/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy +++ b/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy @@ -947,6 +947,20 @@ class Suite implements GroovyInterceptable { return debugPoint } + void testFoldConst(String foldSql) { + String openFoldConstant = "set debug_skip_fold_constant=false"; + sql(openFoldConstant) + logger.info(foldSql) + List> resultByFoldConstant = sql(foldSql) + logger.info("result by fold constant: " + resultByFoldConstant.toString()) + String closeFoldConstant = "set debug_skip_fold_constant=true"; + sql(closeFoldConstant) + logger.info(foldSql) + List> resultExpected = sql(foldSql) + logger.info("result expected: " + resultExpected.toString()) + Assert.assertEquals(resultExpected, resultByFoldConstant) + } + boolean isCloudMode() { return false } diff --git a/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_by_fe.groovy b/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_by_fe.groovy index 33b267f8f752d47..171f8ac411f4467 100644 --- a/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_by_fe.groovy +++ b/regression-test/suites/nereids_p0/expression/fold_constant/fold_constant_by_fe.groovy @@ -161,4 +161,90 @@ suite("test_fold_constant_by_fe") { res = sql """explain select "12" like '%123%'""" assertTrue(res.contains("like")) + // Normal Usage Test Cases + + // Test Case 1: Append missing trailing character + testFoldConst("select append_trailing_char_if_absent('hello', '!')") + // Expected Output: 'hello!' + + // Test Case 2: Trailing character already present + testFoldConst("select append_trailing_char_if_absent('hello!', '!')") + // Expected Output: 'hello!' + + // Test Case 3: Append trailing space + testFoldConst("select append_trailing_char_if_absent('hello', ' ')") + // Expected Output: 'hello ' + + // Test Case 4: Empty string input + testFoldConst("select append_trailing_char_if_absent('', '!')") + // Expected Output: '!' + + // Test Case 5: Append different character + testFoldConst("select append_trailing_char_if_absent('hello', '?')") + // Expected Output: 'hello?' + + // Test Case 6: String ends with a different character + testFoldConst("select append_trailing_char_if_absent('hello?', '!')") + // Expected Output: 'hello?!' + + // Edge and Unusual Usage Test Cases + + // Test Case 7: Input is NULL + testFoldConst("select append_trailing_char_if_absent(NULL, '!')") + // Expected Output: NULL + + // Test Case 8: Trailing character is NULL + testFoldConst("select append_trailing_char_if_absent('hello', NULL)") + // Expected Output: NULL + + // Test Case 9: Empty trailing character + testFoldConst("select append_trailing_char_if_absent('hello', '')") + // Expected Output: Error or no change depending on implementation + + // Test Case 10: Trailing character is more than 1 character long + testFoldConst("select append_trailing_char_if_absent('hello', 'ab')") + // Expected Output: Error + + // Test Case 11: Input string is a number + testFoldConst("select append_trailing_char_if_absent(12345, '!')") + // Expected Output: Error or '12345!' + + // Test Case 12: Trailing character is a number + testFoldConst("select append_trailing_char_if_absent('hello', '1')") + // Expected Output: 'hello1' + + // Test Case 13: Input is a single character + testFoldConst("select append_trailing_char_if_absent('h', '!')") + // Expected Output: 'h!' + + // Test Case 14: Unicode character as input and trailing character + testFoldConst("select append_trailing_char_if_absent('こんにちは', '!')") + // Expected Output: 'こんにちは!' + + // Test Case 15: Multibyte character as trailing character + testFoldConst("select append_trailing_char_if_absent('hello', '😊')") + // Expected Output: 'hello😊' + + // Test Case 16: Long string input + testFoldConst("select append_trailing_char_if_absent('This is a very long string', '.')") + // Expected Output: 'This is a very long string.' + + // Error Handling Test Cases + + // Test Case 17: Invalid trailing character data type (numeric) + testFoldConst("select append_trailing_char_if_absent('hello', 1)") + // Expected Output: Error + + // Test Case 18: Invalid input data type (integer) + testFoldConst("select append_trailing_char_if_absent(12345, '!')") + // Expected Output: Error or '12345!' + + // Test Case 19: Non-ASCII characters + testFoldConst("select append_trailing_char_if_absent('Привет', '!')") + // Expected Output: 'Привет!' + + // Test Case 20: Trailing character with whitespace + testFoldConst("select append_trailing_char_if_absent('hello', ' ')") + // Expected Output: 'hello ' + }