[FLINK-4743] [table] Add support for power(DOUBLE, DECIMAL) function. This closes #2686.
Project: http://git-wip-us.apache.org/repos/asf/flink/repo Commit: http://git-wip-us.apache.org/repos/asf/flink/commit/45651700 Tree: http://git-wip-us.apache.org/repos/asf/flink/tree/45651700 Diff: http://git-wip-us.apache.org/repos/asf/flink/diff/45651700 Branch: refs/heads/master Commit: 4565170088595838ec53f3ca9b898126c62abbbc Parents: d60fe72 Author: anton solovev <[email protected]> Authored: Mon Oct 24 13:47:41 2016 +0400 Committer: Fabian Hueske <[email protected]> Committed: Wed Nov 2 18:30:58 2016 +0100 ---------------------------------------------------------------------- .../table/codegen/calls/BuiltInMethods.scala | 3 +- .../api/table/expressions/InputTypeSpec.scala | 4 +- .../table/functions/utils/MathFunctions.scala | 29 +++++++ .../table/expressions/ScalarFunctionsTest.scala | 90 +++++++++++++++++++- 4 files changed, 122 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flink/blob/45651700/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/codegen/calls/BuiltInMethods.scala ---------------------------------------------------------------------- diff --git a/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/codegen/calls/BuiltInMethods.scala b/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/codegen/calls/BuiltInMethods.scala index a2715f0..6a6898d 100644 --- a/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/codegen/calls/BuiltInMethods.scala +++ b/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/codegen/calls/BuiltInMethods.scala @@ -21,13 +21,14 @@ import java.math.{BigDecimal => JBigDecimal} import org.apache.calcite.linq4j.tree.Types import org.apache.calcite.runtime.SqlFunctions +import org.apache.flink.api.table.functions.utils.MathFunctions object BuiltInMethods { val LOG10 = Types.lookupMethod(classOf[Math], "log10", classOf[Double]) val EXP = Types.lookupMethod(classOf[Math], "exp", classOf[Double]) val POWER = Types.lookupMethod(classOf[Math], "pow", classOf[Double], classOf[Double]) val POWER_DEC = Types.lookupMethod( - classOf[SqlFunctions], "power", classOf[Long], classOf[JBigDecimal]) + classOf[MathFunctions], "power", classOf[Double], classOf[JBigDecimal]) val LN = Types.lookupMethod(classOf[Math], "log", classOf[Double]) val ABS = Types.lookupMethod(classOf[SqlFunctions], "abs", classOf[Double]) val ABS_DEC = Types.lookupMethod(classOf[SqlFunctions], "abs", classOf[JBigDecimal]) http://git-wip-us.apache.org/repos/asf/flink/blob/45651700/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/expressions/InputTypeSpec.scala ---------------------------------------------------------------------- diff --git a/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/expressions/InputTypeSpec.scala b/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/expressions/InputTypeSpec.scala index f545d13..67e44a1 100644 --- a/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/expressions/InputTypeSpec.scala +++ b/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/expressions/InputTypeSpec.scala @@ -49,7 +49,9 @@ trait InputTypeSpec extends Expression { ValidationSuccess } else { ValidationFailure( - s"$this fails on input type checking: ${typeMismatches.mkString("[", ", ", "]")}") + s"""|$this fails on input type checking: ${typeMismatches.mkString("[", ", ", "]")}. + |Operand should be casted to proper type + |""".stripMargin) } } } http://git-wip-us.apache.org/repos/asf/flink/blob/45651700/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/functions/utils/MathFunctions.scala ---------------------------------------------------------------------- diff --git a/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/functions/utils/MathFunctions.scala b/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/functions/utils/MathFunctions.scala new file mode 100644 index 0000000..8a0fe65 --- /dev/null +++ b/flink-libraries/flink-table/src/main/scala/org/apache/flink/api/table/functions/utils/MathFunctions.scala @@ -0,0 +1,29 @@ +/* + * 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.flink.api.table.functions.utils + +import java.math.{BigDecimal => JBigDecimal} + +class MathFunctions {} + +object MathFunctions { + def power(a: Double, b: JBigDecimal): Double = { + Math.pow(a, b.doubleValue()) + } +} http://git-wip-us.apache.org/repos/asf/flink/blob/45651700/flink-libraries/flink-table/src/test/scala/org/apache/flink/api/table/expressions/ScalarFunctionsTest.scala ---------------------------------------------------------------------- diff --git a/flink-libraries/flink-table/src/test/scala/org/apache/flink/api/table/expressions/ScalarFunctionsTest.scala b/flink-libraries/flink-table/src/test/scala/org/apache/flink/api/table/expressions/ScalarFunctionsTest.scala index 46aff01..a6975b9 100644 --- a/flink-libraries/flink-table/src/test/scala/org/apache/flink/api/table/expressions/ScalarFunctionsTest.scala +++ b/flink-libraries/flink-table/src/test/scala/org/apache/flink/api/table/expressions/ScalarFunctionsTest.scala @@ -354,6 +354,7 @@ class ScalarFunctionsTest extends ExpressionTestBase { @Test def testPower(): Unit = { + // f7: int , f4: long, f6: double testAllApis( 'f2.power('f7), "f2.power(f7)", @@ -377,11 +378,94 @@ class ScalarFunctionsTest extends ExpressionTestBase { "f4.power(f5)", "POWER(f4, f5)", math.pow(44.toLong, 4.5.toFloat).toString) + + // f5: float + testAllApis('f5.power('f5), + "f5.power(f5)", + "power(f5, f5)", + math.pow(4.5F, 4.5F).toString) + + testAllApis('f5.power('f6), + "f5.power(f6)", + "power(f5, f6)", + math.pow(4.5F, 4.6D).toString) + + testAllApis('f5.power('f7), + "f5.power(f7)", + "power(f5, f7)", + math.pow(4.5F, 3).toString) + + testAllApis('f5.power('f4), + "f5.power(f4)", + "power(f5, f4)", + math.pow(4.5F, 44L).toString) + + // f22: bigDecimal + // TODO delete casting in SQL when CALCITE-1467 is fixed + testAllApis( + 'f22.cast(Types.DOUBLE).power('f5), + "f22.cast(DOUBLE).power(f5)", + "power(CAST(f22 AS DOUBLE), f5)", + math.pow(2, 4.5F).toString) + + testAllApis( + 'f22.cast(Types.DOUBLE).power('f6), + "f22.cast(DOUBLE).power(f6)", + "power(CAST(f22 AS DOUBLE), f6)", + math.pow(2, 4.6D).toString) + + testAllApis( + 'f22.cast(Types.DOUBLE).power('f7), + "f22.cast(DOUBLE).power(f7)", + "power(CAST(f22 AS DOUBLE), f7)", + math.pow(2, 3).toString) + + testAllApis( + 'f22.cast(Types.DOUBLE).power('f4), + "f22.cast(DOUBLE).power(f4)", + "power(CAST(f22 AS DOUBLE), f4)", + math.pow(2, 44L).toString) + + testAllApis( + 'f6.power('f22.cast(Types.DOUBLE)), + "f6.power(f22.cast(DOUBLE))", + "power(f6, f22)", + math.pow(4.6D, 2).toString) } @Test def testSqrt(): Unit = { testAllApis( + 'f6.sqrt(), + "f6.sqrt", + "SQRT(f6)", + math.sqrt(4.6D).toString) + + testAllApis( + 'f7.sqrt(), + "f7.sqrt", + "SQRT(f7)", + math.sqrt(3).toString) + + testAllApis( + 'f4.sqrt(), + "f4.sqrt", + "SQRT(f4)", + math.sqrt(44L).toString) + + testAllApis( + 'f22.cast(Types.DOUBLE).sqrt(), + "f22.cast(DOUBLE).sqrt", + "SQRT(CAST(f22 AS DOUBLE))", + math.sqrt(2.0).toString) + + testAllApis( + 'f5.sqrt(), + "f5.sqrt", + "SQRT(f5)", + math.pow(4.5F, 0.5).toString) + + testAllApis( 25.sqrt(), "25.sqrt()", "SQRT(25)", @@ -944,7 +1028,7 @@ class ScalarFunctionsTest extends ExpressionTestBase { // ---------------------------------------------------------------------------------------------- def testData = { - val testData = new Row(22) + val testData = new Row(23) testData.setField(0, "This is a test String.") testData.setField(1, true) testData.setField(2, 42.toByte) @@ -967,6 +1051,7 @@ class ScalarFunctionsTest extends ExpressionTestBase { testData.setField(19, 1467012213000L) // +16979 07:23:33.000 testData.setField(20, 25) // +2-01 testData.setField(21, null) + testData.setField(22, BigDecimal("2").bigDecimal) testData } @@ -993,6 +1078,7 @@ class ScalarFunctionsTest extends ExpressionTestBase { Types.TIMESTAMP, Types.INTERVAL_MILLIS, Types.INTERVAL_MONTHS, - Types.BOOLEAN)).asInstanceOf[TypeInformation[Any]] + Types.BOOLEAN, + Types.DECIMAL)).asInstanceOf[TypeInformation[Any]] } }
