You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by fe...@apache.org on 2020/07/27 05:10:45 UTC

[calcite] branch master updated: [CALCITE-2854] Codegen compile error when implementing unary minus function with data type BigDecimal (Qi Yu)

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

fengzhu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/master by this push:
     new b306668  [CALCITE-2854] Codegen compile error when implementing unary minus function with data type BigDecimal (Qi Yu)
b306668 is described below

commit b306668d796a19ade127dce7b392f970cffd4b39
Author: 余启 <yu...@xiaomi.com>
AuthorDate: Fri Jul 17 15:09:33 2020 +0800

    [CALCITE-2854] Codegen compile error when implementing unary minus function with data type BigDecimal (Qi Yu)
---
 .../calcite/adapter/enumerable/RexImpTable.java    | 28 ++++++++++++++++------
 .../org/apache/calcite/util/BuiltInMethod.java     |  4 +++-
 .../apache/calcite/test/ReflectiveSchemaTest.java  | 10 ++++++++
 3 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
index ec913d6..20a86a3 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
@@ -32,7 +32,6 @@ import org.apache.calcite.linq4j.tree.MethodCallExpression;
 import org.apache.calcite.linq4j.tree.OptimizeShuttle;
 import org.apache.calcite.linq4j.tree.ParameterExpression;
 import org.apache.calcite.linq4j.tree.Primitive;
-import org.apache.calcite.linq4j.tree.UnaryExpression;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.rel.type.RelDataTypeFactoryImpl;
@@ -384,8 +383,9 @@ public class RexImpTable {
     defineBinary(MULTIPLY, Multiply, NullPolicy.STRICT, "multiply");
     defineBinary(DIVIDE, Divide, NullPolicy.STRICT, "divide");
     defineBinary(DIVIDE_INTEGER, Divide, NullPolicy.STRICT, "divide");
-    defineUnary(UNARY_MINUS, Negate, NullPolicy.STRICT);
-    defineUnary(UNARY_PLUS, UnaryPlus, NullPolicy.STRICT);
+    defineUnary(UNARY_MINUS, Negate, NullPolicy.STRICT,
+        BuiltInMethod.BIG_DECIMAL_NEGATE.getMethodName());
+    defineUnary(UNARY_PLUS, UnaryPlus, NullPolicy.STRICT, null);
 
     defineMethod(MOD, "mod", NullPolicy.STRICT);
     defineMethod(EXP, "exp", NullPolicy.STRICT);
@@ -710,8 +710,8 @@ public class RexImpTable {
   }
 
   private void defineUnary(SqlOperator operator, ExpressionType expressionType,
-      NullPolicy nullPolicy) {
-    map.put(operator, new UnaryImplementor(expressionType, nullPolicy));
+      NullPolicy nullPolicy, String backupMethodName) {
+    map.put(operator, new UnaryImplementor(expressionType, nullPolicy, backupMethodName));
   }
 
   private void defineBinary(SqlOperator operator, ExpressionType expressionType,
@@ -2181,10 +2181,13 @@ public class RexImpTable {
   /** Implementor for unary operators. */
   private static class UnaryImplementor extends AbstractRexCallImplementor {
     private final ExpressionType expressionType;
+    private final String backupMethodName;
 
-    UnaryImplementor(ExpressionType expressionType, NullPolicy nullPolicy) {
+    UnaryImplementor(ExpressionType expressionType, NullPolicy nullPolicy,
+        String backupMethodName) {
       super(nullPolicy, false);
       this.expressionType = expressionType;
+      this.backupMethodName = backupMethodName;
     }
 
     @Override String getVariableName() {
@@ -2194,7 +2197,18 @@ public class RexImpTable {
     @Override Expression implementSafe(RexToLixTranslator translator,
         RexCall call, List<Expression> argValueList) {
       final Expression argValue = argValueList.get(0);
-      final UnaryExpression e = Expressions.makeUnary(expressionType, argValue);
+
+      final Expression e;
+      //Special case for implementing unary minus with BigDecimal type
+      //for other data type(except BigDecimal) '-' operator is OK, but for
+      //BigDecimal, we should call negate method of BigDecimal
+      if (expressionType == ExpressionType.Negate && argValue.type == BigDecimal.class
+          && null != backupMethodName) {
+        e = Expressions.call(argValue, backupMethodName);
+      } else {
+        e = Expressions.makeUnary(expressionType, argValue);
+      }
+
       if (e.type.equals(argValue.type)) {
         return e;
       }
diff --git a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
index 990e5c1..0b462f1 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -114,6 +114,7 @@ import com.google.common.collect.ImmutableMap;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.math.BigDecimal;
 import java.sql.ResultSet;
 import java.sql.Time;
 import java.sql.Timestamp;
@@ -610,7 +611,8 @@ public enum BuiltInMethod {
   HOPPING(EnumUtils.class, "hopping", Enumerator.class, int.class, long.class,
       long.class, long.class),
   SESSIONIZATION(EnumUtils.class, "sessionize", Enumerator.class, int.class, int.class,
-      long.class);
+      long.class),
+  BIG_DECIMAL_NEGATE(BigDecimal.class, "negate");
 
   public final Method method;
   public final Constructor constructor;
diff --git a/core/src/test/java/org/apache/calcite/test/ReflectiveSchemaTest.java b/core/src/test/java/org/apache/calcite/test/ReflectiveSchemaTest.java
index f0540f7..812060a 100644
--- a/core/src/test/java/org/apache/calcite/test/ReflectiveSchemaTest.java
+++ b/core/src/test/java/org/apache/calcite/test/ReflectiveSchemaTest.java
@@ -1070,4 +1070,14 @@ public class ReflectiveSchemaTest {
             + "from \"s\".\"primesCustomBoxed\"")
         .returnsUnordered("EXPR$0=false\nEXPR$0=false\nEXPR$0=true");
   }
+
+  @Test void testDecimalNegate() {
+    final CalciteAssert.AssertThat with =
+        CalciteAssert.that().withSchema("s", CATCHALL);
+    with.query("select - \"bigDecimal\" from \"s\".\"everyTypes\"")
+        .planContains("negate()")
+        .returnsUnordered(
+            "EXPR$0=0",
+            "EXPR$0=null");
+  }
 }