You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by gi...@apache.org on 2019/03/05 03:18:29 UTC

[incubator-druid] branch master updated: support sin cos etc trigonometric function in sql (#7182)

This is an automated email from the ASF dual-hosted git repository.

gian pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-druid.git


The following commit(s) were added to refs/heads/master by this push:
     new 6511827  support sin cos etc trigonometric function in sql (#7182)
6511827 is described below

commit 65118277a3be4900939bcfe102f5ff491cb33d9e
Author: Xue Yu <27...@qq.com>
AuthorDate: Tue Mar 5 11:18:22 2019 +0800

    support sin cos etc trigonometric function in sql (#7182)
    
    * support triangle function in sql
    
    * feedback address
---
 .../java/org/apache/druid/math/expr/Function.java  | 37 +++++++++++++++++
 docs/content/misc/math-expr.md                     |  2 +
 docs/content/querying/sql.md                       |  8 ++++
 .../sql/calcite/planner/DruidOperatorTable.java    |  9 +++++
 .../apache/druid/sql/calcite/CalciteQueryTest.java | 47 ++++++++++++++++++++++
 5 files changed, 103 insertions(+)

diff --git a/core/src/main/java/org/apache/druid/math/expr/Function.java b/core/src/main/java/org/apache/druid/math/expr/Function.java
index 2424755..2b03bfc 100644
--- a/core/src/main/java/org/apache/druid/math/expr/Function.java
+++ b/core/src/main/java/org/apache/druid/math/expr/Function.java
@@ -122,6 +122,27 @@ interface Function
     }
   }
 
+  class Pi implements Function
+  {
+    private static final double PI = Math.PI;
+
+    @Override
+    public String name()
+    {
+      return "pi";
+    }
+
+    @Override
+    public ExprEval apply(List<Expr> args, Expr.ObjectBinding bindings)
+    {
+      if (args.size() >= 1) {
+        throw new IAE("Function[%s] needs 0 argument", name());
+      }
+
+      return ExprEval.of(PI);
+    }
+  }
+
   class Abs extends SingleParamMath
   {
     @Override
@@ -248,6 +269,22 @@ interface Function
     }
   }
 
+  class Cot extends SingleParamMath
+  {
+    @Override
+    public String name()
+    {
+      return "cot";
+    }
+
+    @Override
+    protected ExprEval eval(double param)
+    {
+      return ExprEval.of(Math.cos(param) / Math.sin(param));
+    }
+  }
+
+
   class Div extends DoubleParamMath
   {
     @Override
diff --git a/docs/content/misc/math-expr.md b/docs/content/misc/math-expr.md
index ff749ea..a116682 100644
--- a/docs/content/misc/math-expr.md
+++ b/docs/content/misc/math-expr.md
@@ -109,6 +109,7 @@ See javadoc of java.lang.Math for detailed explanation for each function.
 |copysign|copysign(x) would return the first floating-point argument with the sign of the second floating-point argument|
 |cos|cos(x) would return the trigonometric cosine of x|
 |cosh|cosh(x) would return the hyperbolic cosine of x|
+|cot|cot(x) would return the trigonometric cotangent of an angle x|
 |div|div(x,y) is integer division of x by y|
 |exp|exp(x) would return Euler's number raised to the power of x|
 |expm1|expm1(x) would return e^x-1|
@@ -122,6 +123,7 @@ See javadoc of java.lang.Math for detailed explanation for each function.
 |min|min(x, y) would return the smaller of two values|
 |nextafter|nextafter(x, y) would return the floating-point number adjacent to the x in the direction of the y|
 |nextUp|nextUp(x) would return the floating-point value adjacent to x in the direction of positive infinity|
+|pi|pi would return the constant value of the π |
 |pow|pow(x, y) would return the value of the x raised to the power of y|
 |remainder|remainder(x, y) would return the remainder operation on two arguments as prescribed by the IEEE 754 standard|
 |rint|rint(x) would return value that is closest in value to x and is equal to a mathematical integer|
diff --git a/docs/content/querying/sql.md b/docs/content/querying/sql.md
index 31e0109..d708850 100644
--- a/docs/content/querying/sql.md
+++ b/docs/content/querying/sql.md
@@ -147,6 +147,14 @@ Numeric functions will return 64 bit integers or 64 bit floats, depending on the
 |`x * y`|Multiplication.|
 |`x / y`|Division.|
 |`MOD(x, y)`|Modulo (remainder of x divided by y).|
+|`SIN(expr)`|Trigonometric sine of an angle expr.|
+|`COS(expr)`|Trigonometric cosine of an angle expr.|
+|`TAN(expr)`|Trigonometric tangent of an angle expr.|
+|`COT(expr)`|Trigonometric cotangent of an angle expr.|
+|`ASIN(expr)`|Arc sine of expr.|
+|`ACOS(expr)`|Arc cosine of expr.|
+|`ATAN(expr)`|Arc tangent of expr.|
+|`ATAN2(y, x)`|Angle theta from the conversion of rectangular coordinates (x, y) to polar * coordinates (r, theta).|
 
 ### String functions
 
diff --git a/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidOperatorTable.java b/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidOperatorTable.java
index 601303d..b355095 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidOperatorTable.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidOperatorTable.java
@@ -121,6 +121,15 @@ public class DruidOperatorTable implements SqlOperatorTable
           .add(new DirectOperatorConversion(SqlStdOperatorTable.REPLACE, "replace"))
           .add(new DirectOperatorConversion(SqlStdOperatorTable.SQRT, "sqrt"))
           .add(new DirectOperatorConversion(SqlStdOperatorTable.UPPER, "upper"))
+          .add(new DirectOperatorConversion(SqlStdOperatorTable.PI, "pi"))
+          .add(new DirectOperatorConversion(SqlStdOperatorTable.SIN, "sin"))
+          .add(new DirectOperatorConversion(SqlStdOperatorTable.COS, "cos"))
+          .add(new DirectOperatorConversion(SqlStdOperatorTable.TAN, "tan"))
+          .add(new DirectOperatorConversion(SqlStdOperatorTable.COT, "cot"))
+          .add(new DirectOperatorConversion(SqlStdOperatorTable.ASIN, "asin"))
+          .add(new DirectOperatorConversion(SqlStdOperatorTable.ACOS, "acos"))
+          .add(new DirectOperatorConversion(SqlStdOperatorTable.ATAN, "atan"))
+          .add(new DirectOperatorConversion(SqlStdOperatorTable.ATAN2, "atan2"))
           .add(new UnaryPrefixOperatorConversion(SqlStdOperatorTable.NOT, "!"))
           .add(new UnaryPrefixOperatorConversion(SqlStdOperatorTable.UNARY_MINUS, "-"))
           .add(new UnaryFunctionOperatorConversion(SqlStdOperatorTable.IS_NULL, "isnull"))
diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
index ad6030f..839d892 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
@@ -7598,4 +7598,51 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
         )
     );
   }
+
+  @Test
+  public void testTrigonometricFunction() throws Exception
+  {
+    testQuery(
+        PLANNER_CONFIG_DEFAULT,
+        QUERY_CONTEXT_DONT_SKIP_EMPTY_BUCKETS,
+        "SELECT exp(count(*)) + 10, sin(pi / 6), cos(pi / 6), tan(pi / 6), cot(pi / 6)," +
+            "asin(exp(count(*)) / 2), acos(exp(count(*)) / 2), atan(exp(count(*)) / 2), atan2(exp(count(*)), 1) " +
+            "FROM druid.foo WHERE  dim2 = 0",
+        CalciteTests.REGULAR_USER_AUTH_RESULT,
+        ImmutableList.of(Druids.newTimeseriesQueryBuilder()
+                               .dataSource(CalciteTests.DATASOURCE1)
+                               .intervals(querySegmentSpec(Filtration.eternity()))
+                               .filters(selector("dim2", "0", null))
+                               .granularity(Granularities.ALL)
+                               .aggregators(aggregators(
+                                   new CountAggregatorFactory("a0")
+                               ))
+                               .postAggregators(
+                                   expresionPostAgg("p0", "(exp(\"a0\") + 10)"),
+                                   expresionPostAgg("p1", "sin((pi() / 6))"),
+                                   expresionPostAgg("p2", "cos((pi() / 6))"),
+                                   expresionPostAgg("p3", "tan((pi() / 6))"),
+                                   expresionPostAgg("p4", "cot((pi() / 6))"),
+                                   expresionPostAgg("p5", "asin((exp(\"a0\") / 2))"),
+                                   expresionPostAgg("p6", "acos((exp(\"a0\") / 2))"),
+                                   expresionPostAgg("p7", "atan((exp(\"a0\") / 2))"),
+                                   expresionPostAgg("p8", "atan2(exp(\"a0\"),1)")
+                               )
+                               .context(QUERY_CONTEXT_DONT_SKIP_EMPTY_BUCKETS)
+                               .build()),
+        ImmutableList.of(
+            new Object[]{
+                11.0,
+                Math.sin(Math.PI / 6),
+                Math.cos(Math.PI / 6),
+                Math.tan(Math.PI / 6),
+                Math.cos(Math.PI / 6) / Math.sin(Math.PI / 6),
+                Math.asin(0.5),
+                Math.acos(0.5),
+                Math.atan(0.5),
+                Math.atan2(1, 1)
+            }
+        )
+    );
+  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org