Repository: drill
Updated Branches:
  refs/heads/master 2b4283df5 -> 4b58ac8b7


DRILL-1897: Fix return type of functions to be nullable during planning phase


Project: http://git-wip-us.apache.org/repos/asf/drill/repo
Commit: http://git-wip-us.apache.org/repos/asf/drill/commit/4b58ac8b
Tree: http://git-wip-us.apache.org/repos/asf/drill/tree/4b58ac8b
Diff: http://git-wip-us.apache.org/repos/asf/drill/diff/4b58ac8b

Branch: refs/heads/master
Commit: 4b58ac8b7a4cb36b50773fab3d9b2774bae953ac
Parents: 2b4283d
Author: Mehant Baid <meha...@gmail.com>
Authored: Wed Mar 4 19:08:46 2015 -0800
Committer: Mehant Baid <meha...@gmail.com>
Committed: Thu Mar 5 23:35:55 2015 -0800

----------------------------------------------------------------------
 .../drill/exec/planner/sql/HiveUDFOperator.java      | 14 ++++++++++++--
 .../drill/exec/planner/sql/DrillSqlOperator.java     | 15 +++++++++++++--
 .../drill/exec/fn/impl/TestAggregateFunctions.java   | 11 +++++++++++
 3 files changed, 36 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/drill/blob/4b58ac8b/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/planner/sql/HiveUDFOperator.java
----------------------------------------------------------------------
diff --git 
a/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/planner/sql/HiveUDFOperator.java
 
b/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/planner/sql/HiveUDFOperator.java
index 71860c3..7524690 100644
--- 
a/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/planner/sql/HiveUDFOperator.java
+++ 
b/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/planner/sql/HiveUDFOperator.java
@@ -18,7 +18,9 @@
 
 package org.apache.drill.exec.planner.sql;
 
+import com.fasterxml.jackson.databind.type.TypeFactory;
 import org.eigenbase.reltype.RelDataType;
+import org.eigenbase.reltype.RelDataTypeFactory;
 import org.eigenbase.sql.SqlCall;
 import org.eigenbase.sql.SqlCallBinding;
 import org.eigenbase.sql.SqlFunction;
@@ -26,6 +28,7 @@ import org.eigenbase.sql.SqlFunctionCategory;
 import org.eigenbase.sql.SqlIdentifier;
 import org.eigenbase.sql.SqlOperandCountRange;
 import org.eigenbase.sql.SqlOperator;
+import org.eigenbase.sql.SqlOperatorBinding;
 import org.eigenbase.sql.parser.SqlParserPos;
 import org.eigenbase.sql.type.SqlOperandCountRanges;
 import org.eigenbase.sql.type.SqlOperandTypeChecker;
@@ -42,10 +45,17 @@ public class HiveUDFOperator extends SqlFunction {
 
   @Override
   public RelDataType deriveType(SqlValidator validator, SqlValidatorScope 
scope, SqlCall call) {
-    return validator.getTypeFactory().createSqlType(SqlTypeName.ANY);
+    RelDataTypeFactory factory = validator.getTypeFactory();
+    return 
factory.createTypeWithNullability(factory.createSqlType(SqlTypeName.ANY), true);
   }
 
-  /** Argument Checker for variable number of arguments */
+  @Override
+  public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
+    RelDataTypeFactory factory = opBinding.getTypeFactory();
+    return 
factory.createTypeWithNullability(factory.createSqlType(SqlTypeName.ANY), true);
+  }
+
+    /** Argument Checker for variable number of arguments */
   public static class ArgChecker implements SqlOperandTypeChecker {
 
     public static ArgChecker INSTANCE = new ArgChecker();

http://git-wip-us.apache.org/repos/asf/drill/blob/4b58ac8b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/DrillSqlOperator.java
----------------------------------------------------------------------
diff --git 
a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/DrillSqlOperator.java
 
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/DrillSqlOperator.java
index d9fc997..6b54c43 100644
--- 
a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/DrillSqlOperator.java
+++ 
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/DrillSqlOperator.java
@@ -55,12 +55,22 @@ public class DrillSqlOperator extends SqlFunction {
     return factory.createSqlType(SqlTypeName.ANY);
   }
 
+  private RelDataType getNullableReturnDataType(final RelDataTypeFactory 
factory) {
+    return factory.createTypeWithNullability(getReturnDataType(factory), true);
+  }
+
   @Override
   public RelDataType deriveType(SqlValidator validator, SqlValidatorScope 
scope, SqlCall call) {
     if (NONE.equals(returnType)) {
       return validator.getTypeFactory().createSqlType(SqlTypeName.ANY);
     }
-    return getReturnDataType(validator.getTypeFactory());
+    /*
+     * We return a nullable output type both in validation phase and in
+     * Sql to Rel phase. We don't know the type of the output until runtime
+     * hence have to choose the least restrictive type to avoid any wrong
+     * results.
+     */
+    return getNullableReturnDataType(validator.getTypeFactory());
   }
 
   @Override
@@ -68,6 +78,7 @@ public class DrillSqlOperator extends SqlFunction {
     if (NONE.equals(returnType)) {
       return super.inferReturnType(opBinding);
     }
-    return getReturnDataType(opBinding.getTypeFactory());
+
+    return getNullableReturnDataType(opBinding.getTypeFactory());
   }
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/4b58ac8b/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestAggregateFunctions.java
----------------------------------------------------------------------
diff --git 
a/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestAggregateFunctions.java
 
b/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestAggregateFunctions.java
index f8966e8..f3c7fa5 100644
--- 
a/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestAggregateFunctions.java
+++ 
b/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestAggregateFunctions.java
@@ -157,4 +157,15 @@ public class TestAggregateFunctions extends BaseTestQuery {
     test("alter session set `planner.slice_target` = 100000");
   }
 
+  @Test
+  public void testAvgWithNullableScalarFunction() throws Exception {
+    String query = " select avg(length(b1)) as col from 
cp.`jsoninput/nullable1.json`";
+    testBuilder()
+        .sqlQuery(query)
+        .unOrdered()
+        .baselineColumns("col")
+        .baselineValues(3.0d)
+        .go();
+  }
+
 }

Reply via email to