This is an automated email from the ASF dual-hosted git repository. godfrey pushed a commit to branch release-1.14 in repository https://gitbox.apache.org/repos/asf/flink.git
commit 8c7cbcd9744378dccb4b6ab0493c7d273c69dfef Author: paul8263 <[email protected]> AuthorDate: Tue Sep 7 17:13:10 2021 +0800 [FLINK-23614][table-planner] The resulting scale of TRUNCATE(DECIMAL) is not correct This closes #16740 (cherry picked from commit e55e6649da41621872f3a847dcd1dad2d97b017a) --- .../functions/BuiltInFunctionDefinitions.java | 2 +- .../functions/sql/FlinkSqlOperatorTable.java | 10 +++- .../planner/functions/MathFunctionsITCase.java | 10 +++- .../planner/expressions/ScalarFunctionsTest.scala | 68 ++++++++++++++++++---- .../validation/ScalarFunctionsValidationTest.scala | 2 +- .../planner/runtime/batch/sql/CalcITCase.scala | 35 +++++++++++ 6 files changed, 112 insertions(+), 15 deletions(-) diff --git a/flink-table/flink-table-common/src/main/java/org/apache/flink/table/functions/BuiltInFunctionDefinitions.java b/flink-table/flink-table-common/src/main/java/org/apache/flink/table/functions/BuiltInFunctionDefinitions.java index 1cd31cf..022b7b1 100644 --- a/flink-table/flink-table-common/src/main/java/org/apache/flink/table/functions/BuiltInFunctionDefinitions.java +++ b/flink-table/flink-table-common/src/main/java/org/apache/flink/table/functions/BuiltInFunctionDefinitions.java @@ -1136,7 +1136,7 @@ public final class BuiltInFunctionDefinitions { sequence( logical(LogicalTypeFamily.NUMERIC), logical(LogicalTypeRoot.INTEGER)))) - .outputTypeStrategy(nullableIfArgs(argument(0))) + .outputTypeStrategy(nullableIfArgs(SpecificTypeStrategies.ROUND)) .build(); // -------------------------------------------------------------------------------------------- diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/functions/sql/FlinkSqlOperatorTable.java b/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/functions/sql/FlinkSqlOperatorTable.java index 2c6d46e..cd0052d 100644 --- a/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/functions/sql/FlinkSqlOperatorTable.java +++ b/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/functions/sql/FlinkSqlOperatorTable.java @@ -224,6 +224,15 @@ public class FlinkSqlOperatorTable extends ReflectiveSqlOperatorTable { OperandTypes.or(OperandTypes.NUMERIC_INTEGER, OperandTypes.NUMERIC), SqlFunctionCategory.NUMERIC); + public static final SqlFunction TRUNCATE = + new SqlFunction( + "TRUNCATE", + SqlKind.OTHER_FUNCTION, + FlinkReturnTypes.ROUND_FUNCTION_NULLABLE, + null, + OperandTypes.or(OperandTypes.NUMERIC_INTEGER, OperandTypes.NUMERIC), + SqlFunctionCategory.NUMERIC); + public static final SqlFunction BIN = new SqlFunction( "BIN", @@ -1125,7 +1134,6 @@ public class FlinkSqlOperatorTable extends ReflectiveSqlOperatorTable { public static final SqlFunction PI = SqlStdOperatorTable.PI; public static final SqlFunction RAND = SqlStdOperatorTable.RAND; public static final SqlFunction RAND_INTEGER = SqlStdOperatorTable.RAND_INTEGER; - public static final SqlFunction TRUNCATE = SqlStdOperatorTable.TRUNCATE; // TIME FUNCTIONS public static final SqlFunction YEAR = SqlStdOperatorTable.YEAR; diff --git a/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/MathFunctionsITCase.java b/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/MathFunctionsITCase.java index c7ff747..0d982dc 100644 --- a/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/MathFunctionsITCase.java +++ b/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/MathFunctionsITCase.java @@ -115,6 +115,14 @@ public class MathFunctionsITCase extends BuiltInFunctionTestBase { $("f0").round(2), "ROUND(f0, 2)", new BigDecimal("12345.12"), - DataTypes.DECIMAL(8, 2).notNull())); + DataTypes.DECIMAL(8, 2).notNull()), + TestSpec.forFunction(BuiltInFunctionDefinitions.TRUNCATE) + .onFieldsWithData(new BigDecimal("123.456")) + // TRUNCATE(DECIMAL(6, 3) NOT NULL, 2) => DECIMAL(6, 2) NOT NULL + .testResult( + $("f0").truncate(2), + "TRUNCATE(f0, 2)", + new BigDecimal("123.45"), + DataTypes.DECIMAL(6, 2).notNull())); } } diff --git a/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/expressions/ScalarFunctionsTest.scala b/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/expressions/ScalarFunctionsTest.scala index 41514e5..c0bf7f7 100644 --- a/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/expressions/ScalarFunctionsTest.scala +++ b/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/expressions/ScalarFunctionsTest.scala @@ -1379,39 +1379,71 @@ class ScalarFunctionsTest extends ScalarTypesTestBase { "0.4") testAllApis( + 'f29.truncate(), + "f29.truncate()", + "truncate(f29)", + "0.0") + + testAllApis( 'f31.truncate('f7), "f31.truncate(f7)", "truncate(f31, f7)", "-0.123") testAllApis( + 'f31.truncate(), + "f31.truncate()", + "truncate(f31)", + "0") + + testAllApis( 'f4.truncate('f32), "f4.truncate(f32)", "truncate(f4, f32)", "40") testAllApis( + 'f4.truncate(), + "f4.truncate()", + "truncate(f4)", + "44") + + testAllApis( 'f28.cast(DataTypes.DOUBLE).truncate(1), "f28.cast(DOUBLE).truncate(1)", "truncate(cast(f28 as DOUBLE), 1)", "0.4") + testAllApis( + 'f28.cast(DataTypes.DOUBLE).truncate(), + "f28.cast(DOUBLE).truncate()", + "truncate(cast(f28 as DOUBLE))", + "0.0") + // TODO: ignore TableApiTest for cast to DECIMAL(p, s) is not support now. // see https://issues.apache.org/jira/browse/FLINK-13651 -// testAllApis( -// 'f31.cast(DataTypes.DECIMAL(38, 18)).truncate(2), -// "f31.cast(DECIMAL(10, 10)).truncate(2)", -// "truncate(cast(f31 as decimal(38, 18)), 2)", -// "-0.12") -// -// testAllApis( -// 'f36.cast(DataTypes.DECIMAL(38, 18)).truncate(), -// "f36.cast(DECIMAL(10, 10)).truncate()", -// "truncate(42.324)", -// "42") + // testAllApis( + // 'f31.cast(DataTypes.DECIMAL(38, 18)).truncate(2), + // "f31.cast(DECIMAL(10, 10)).truncate(2)", + // "truncate(cast(f31 as decimal(38, 18)), 2)", + // "-0.12") + // + // testAllApis( + // 'f36.cast(DataTypes.DECIMAL(38, 18)).truncate(), + // "f36.cast(DECIMAL(10, 10)).truncate()", + // "truncate(42.324)", + // "42") testSqlApi("truncate(cast(f31 as decimal(38, 18)), 2)", "-0.12") + testSqlApi("truncate(cast(f31 as decimal(38, 18)))", "0") + + testAllApis( + 'f28.cast(DataTypes.FLOAT).truncate(1), + "f28.cast(FLOAT).truncate(1)", + "truncate(cast(f28 as float), 1)", + "0.4") + testAllApis( 'f5.cast(DataTypes.FLOAT).truncate(), "f5.cast(FLOAT).truncate()", @@ -1430,6 +1462,12 @@ class ScalarFunctionsTest extends ScalarTypesTestBase { "truncate(42, -3)", "0") + testAllApis( + 42.truncate(), + "42.truncate()", + "truncate(42)", + "42") + // The validation parameter is null testAllApis( 'f33.cast(DataTypes.INT).truncate(1), @@ -1460,6 +1498,14 @@ class ScalarFunctionsTest extends ScalarTypesTestBase { "f33.cast(DOUBLE).truncate()", "truncate(cast(null as double))", "null") + + // TODO: ignore TableApiTest for cast to DECIMAL(p, s) is not support now. + // see https://issues.apache.org/jira/browse/FLINK-13651 + // testAllApis( + // 'f33.cast(DataTypes.DECIMAL(10, 5)).truncate(), + // "f33.cast(DECIMAL(10, 5)).truncate()", + // "truncate(cast(null as decimal(10, 5)))", + // "null") } // ---------------------------------------------------------------------------------------------- diff --git a/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/expressions/validation/ScalarFunctionsValidationTest.scala b/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/expressions/validation/ScalarFunctionsValidationTest.scala index 2634b68..d1760dc 100644 --- a/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/expressions/validation/ScalarFunctionsValidationTest.scala +++ b/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/expressions/validation/ScalarFunctionsValidationTest.scala @@ -94,7 +94,7 @@ class ScalarFunctionsValidationTest extends ScalarTypesTestBase { @Test def testInvalidTruncate2(): Unit = { - thrown.expect(classOf[CodeGenException]) + thrown.expect(classOf[ValidationException]) // The one argument is of type String testSqlApi( "TRUNCATE('abc')", diff --git a/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/runtime/batch/sql/CalcITCase.scala b/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/runtime/batch/sql/CalcITCase.scala index 1088e89..a357ceb 100644 --- a/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/runtime/batch/sql/CalcITCase.scala +++ b/flink-table/flink-table-planner/src/test/scala/org/apache/flink/table/planner/runtime/batch/sql/CalcITCase.scala @@ -1069,6 +1069,41 @@ class CalcITCase extends BatchTestBase { } @Test + def testTruncate(): Unit = { + checkResult( + "SELECT TRUNCATE(CAST(123.456 AS DOUBLE), 2)", + Seq(row(123.45))) + + checkResult( + "SELECT TRUNCATE(CAST(123.456 AS DOUBLE))", + Seq(row(123.0))) + + checkResult( + "SELECT TRUNCATE(CAST(123.456 AS FLOAT), 2)", + Seq(row(123.45f))) + + checkResult( + "SELECT TRUNCATE(CAST(123.456 AS FLOAT))", + Seq(row(123.0f))) + + checkResult( + "SELECT TRUNCATE(123, -1)", + Seq(row(120))) + + checkResult( + "SELECT TRUNCATE(123, -2)", + Seq(row(100))) + + checkResult( + "SELECT TRUNCATE(CAST(123.456 AS DECIMAL(6, 3)), 2)", + Seq(row(new java.math.BigDecimal("123.45")))) + + checkResult( + "SELECT TRUNCATE(CAST(123.456 AS DECIMAL(6, 3)))", + Seq(row(new java.math.BigDecimal("123")))) + } + + @Test def testStringUdf(): Unit = { registerFunction("myFunc", MyStringFunc) checkResult(
