drill-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From amansi...@apache.org
Subject drill git commit: DRILL-4906: CASE Expression with constant generates class exception
Date Thu, 06 Oct 2016 01:10:06 GMT
Repository: drill
Updated Branches:
  refs/heads/master 229571533 -> 1375a0065


DRILL-4906: CASE Expression with constant generates class exception

Tests for different data types

close apache/drill#598


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

Branch: refs/heads/master
Commit: 1375a0065f1acae4ff5edf3c6370b7ad25f188c4
Parents: 2295715
Author: Serhii-Harnyk <serhii.harnyk@gmail.com>
Authored: Thu Sep 22 15:06:10 2016 +0300
Committer: Aman Sinha <asinha@maprtech.com>
Committed: Wed Oct 5 17:38:43 2016 -0700

----------------------------------------------------------------------
 .../expr/fn/impl/StringFunctionHelpers.java     |   8 +
 .../planner/logical/DrillConstExecutor.java     | 297 ++++++++++++-------
 .../planner/logical/TestCaseNullableTypes.java  | 127 ++++++++
 3 files changed, 320 insertions(+), 112 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/drill/blob/1375a006/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/StringFunctionHelpers.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/StringFunctionHelpers.java
b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/StringFunctionHelpers.java
index 3bc8253..88f3417 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/StringFunctionHelpers.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/StringFunctionHelpers.java
@@ -21,6 +21,7 @@ package org.apache.drill.exec.expr.fn.impl;
 import io.netty.buffer.DrillBuf;
 import io.netty.util.internal.PlatformDependent;
 
+import org.apache.drill.exec.expr.holders.NullableVarCharHolder;
 import org.apache.drill.exec.expr.holders.VarCharHolder;
 import org.apache.drill.exec.memory.BoundsChecking;
 import org.joda.time.chrono.ISOChronology;
@@ -194,6 +195,13 @@ public class StringFunctionHelpers {
     return toStringFromUTF8(varCharHolder.start, varCharHolder.end, varCharHolder.buffer);
   }
 
+  /**
+   * Convert a NullableVarCharHolder to a String.
+   */
+  public static String getStringFromVarCharHolder(NullableVarCharHolder varCharHolder) {
+    return toStringFromUTF8(varCharHolder.start, varCharHolder.end, varCharHolder.buffer);
+  }
+
   public static String toStringFromUTF8(int start, int end, DrillBuf buffer) {
     byte[] buf = new byte[end - start];
     buffer.getBytes(start, buf, 0, end - start);

http://git-wip-us.apache.org/repos/asf/drill/blob/1375a006/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillConstExecutor.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillConstExecutor.java
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillConstExecutor.java
index 96579db..4a0f8fa 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillConstExecutor.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillConstExecutor.java
@@ -17,9 +17,9 @@
  ******************************************************************************/
 package org.apache.drill.exec.planner.logical;
 
+import com.google.common.base.Function;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import org.apache.calcite.avatica.util.TimeUnit;
+import io.netty.buffer.DrillBuf;
 import org.apache.drill.common.exceptions.DrillRuntimeException;
 import org.apache.drill.common.expression.ErrorCollectorImpl;
 import org.apache.drill.common.expression.ExpressionStringBuilder;
@@ -43,18 +43,30 @@ import org.apache.drill.exec.expr.holders.Float8Holder;
 import org.apache.drill.exec.expr.holders.IntHolder;
 import org.apache.drill.exec.expr.holders.IntervalDayHolder;
 import org.apache.drill.exec.expr.holders.IntervalYearHolder;
+import org.apache.drill.exec.expr.holders.NullableBigIntHolder;
+import org.apache.drill.exec.expr.holders.NullableBitHolder;
+import org.apache.drill.exec.expr.holders.NullableDateHolder;
+import org.apache.drill.exec.expr.holders.NullableDecimal18Holder;
+import org.apache.drill.exec.expr.holders.NullableDecimal28SparseHolder;
+import org.apache.drill.exec.expr.holders.NullableDecimal38SparseHolder;
+import org.apache.drill.exec.expr.holders.NullableDecimal9Holder;
+import org.apache.drill.exec.expr.holders.NullableFloat4Holder;
+import org.apache.drill.exec.expr.holders.NullableFloat8Holder;
+import org.apache.drill.exec.expr.holders.NullableIntHolder;
+import org.apache.drill.exec.expr.holders.NullableIntervalDayHolder;
+import org.apache.drill.exec.expr.holders.NullableIntervalYearHolder;
+import org.apache.drill.exec.expr.holders.NullableTimeHolder;
+import org.apache.drill.exec.expr.holders.NullableTimeStampHolder;
+import org.apache.drill.exec.expr.holders.NullableVarCharHolder;
 import org.apache.drill.exec.expr.holders.TimeHolder;
 import org.apache.drill.exec.expr.holders.TimeStampHolder;
 import org.apache.drill.exec.expr.holders.ValueHolder;
 import org.apache.drill.exec.expr.holders.VarCharHolder;
 import org.apache.drill.exec.ops.UdfUtilities;
 import org.apache.calcite.plan.RelOptPlanner;
-import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.sql.SqlIntervalQualifier;
-import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.util.NlsString;
 import org.apache.drill.exec.planner.physical.PlannerSettings;
@@ -64,6 +76,7 @@ import org.joda.time.DateTimeZone;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.util.Calendar;
 import java.util.List;
 
 public class DrillConstExecutor implements RelOptPlanner.Executor {
@@ -106,12 +119,12 @@ public class DrillConstExecutor implements RelOptPlanner.Executor {
   }
 
   @Override
-  public void reduce(RexBuilder rexBuilder, List<RexNode> constExps, List<RexNode>
reducedValues) {
-    for (RexNode newCall : constExps) {
+  public void reduce(final RexBuilder rexBuilder, List<RexNode> constExps, final List<RexNode>
reducedValues) {
+    for (final RexNode newCall : constExps) {
       LogicalExpression logEx = DrillOptiq.toDrill(new DrillParseContext(plannerSettings),
null /* input rel */, newCall);
 
       ErrorCollectorImpl errors = new ErrorCollectorImpl();
-      LogicalExpression materializedExpr = ExpressionTreeMaterializer.materialize(logEx,
null, errors, funcImplReg);
+      final LogicalExpression materializedExpr = ExpressionTreeMaterializer.materialize(logEx,
null, errors, funcImplReg);
       if (errors.getErrorCount() != 0) {
         String message = String.format(
             "Failure while materializing expression in constant expression evaluator [%s].
 Errors: %s",
@@ -129,7 +142,7 @@ public class DrillConstExecutor implements RelOptPlanner.Executor {
       }
 
       ValueHolder output = InterpreterEvaluator.evaluateConstantExpr(udfUtilities, materializedExpr);
-      RelDataTypeFactory typeFactory = rexBuilder.getTypeFactory();
+      final RelDataTypeFactory typeFactory = rexBuilder.getTypeFactory();
 
       if (materializedExpr.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL &&
TypeHelper.isNull(output)) {
         SqlTypeName sqlTypeName = TypeInferenceUtils.getCalciteTypeFromDrillType(materializedExpr.getMajorType().getMinorType());
@@ -143,116 +156,176 @@ public class DrillConstExecutor implements RelOptPlanner.Executor
{
         continue;
       }
 
-        switch(materializedExpr.getMajorType().getMinorType()) {
-          case INT:
-            reducedValues.add(rexBuilder.makeLiteral(
-                new BigDecimal(((IntHolder)output).value),
-                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.INTEGER,
newCall.getType().isNullable()),
-                false));
-            break;
-          case BIGINT:
-            reducedValues.add(rexBuilder.makeLiteral(
-                new BigDecimal(((BigIntHolder)output).value),
-                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.BIGINT,
newCall.getType().isNullable()),
-                false));
-            break;
-          case FLOAT4:
-            reducedValues.add(rexBuilder.makeLiteral(
-                new BigDecimal(((Float4Holder)output).value),
-                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.FLOAT,
newCall.getType().isNullable()),
-                false));
-            break;
-          case FLOAT8:
-            reducedValues.add(rexBuilder.makeLiteral(
-                new BigDecimal(((Float8Holder)output).value),
-                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.DOUBLE,
newCall.getType().isNullable()),
-                false));
-            break;
-          case VARCHAR:
-            reducedValues.add(rexBuilder.makeCharLiteral(
-                new NlsString(StringFunctionHelpers.getStringFromVarCharHolder((VarCharHolder)output),
null, null)));
-            break;
-          case BIT:
-            reducedValues.add(rexBuilder.makeLiteral(
-                ((BitHolder)output).value == 1 ? true : false,
-                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.BOOLEAN,
newCall.getType().isNullable()),
-                false));
-            break;
-          case DATE:
-            reducedValues.add(rexBuilder.makeLiteral(
-                new DateTime(((DateHolder) output).value, DateTimeZone.UTC).toCalendar(null),
-                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.DATE,
newCall.getType().isNullable()),
-                false));
-            break;
-          case DECIMAL9:
-            reducedValues.add(rexBuilder.makeLiteral(
-                new BigDecimal(BigInteger.valueOf(((Decimal9Holder) output).value), ((Decimal9Holder)output).scale),
+      Function<ValueHolder, RexNode> literator = new Function<ValueHolder, RexNode>()
{
+        @Override
+        public RexNode apply(ValueHolder output) {
+          switch(materializedExpr.getMajorType().getMinorType()) {
+            case INT: {
+              int value = (materializedExpr.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL)
?
+                ((NullableIntHolder) output).value : ((IntHolder) output).value;
+              return rexBuilder.makeLiteral(new BigDecimal(value),
+                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.INTEGER,
newCall.getType().isNullable()), false);
+            }
+            case BIGINT: {
+              long value = (materializedExpr.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL)
?
+                ((NullableBigIntHolder) output).value : ((BigIntHolder) output).value;
+              return rexBuilder.makeLiteral(new BigDecimal(value),
+                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.BIGINT,
newCall.getType().isNullable()), false);
+            }
+            case FLOAT4: {
+              float value = (materializedExpr.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL)
?
+                ((NullableFloat4Holder) output).value : ((Float4Holder) output).value;
+              return rexBuilder.makeLiteral(new BigDecimal(value),
+                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.FLOAT,
newCall.getType().isNullable()), false);
+            }
+            case FLOAT8: {
+              double value = (materializedExpr.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL)
?
+                ((NullableFloat8Holder) output).value : ((Float8Holder) output).value;
+              return rexBuilder.makeLiteral(new BigDecimal(value),
+                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.DOUBLE,
newCall.getType().isNullable()), false);
+            }
+            case VARCHAR: {
+              String value = (materializedExpr.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL)
?
+                StringFunctionHelpers.getStringFromVarCharHolder((NullableVarCharHolder)output)
:
+                StringFunctionHelpers.getStringFromVarCharHolder((VarCharHolder)output);
+              return rexBuilder.makeLiteral(value,
+                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.VARCHAR,
newCall.getType().isNullable()), false);
+            }
+            case BIT: {
+              boolean value = (materializedExpr.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL)
?
+                ((NullableBitHolder) output).value == 1 : ((BitHolder) output).value == 1;
+              return rexBuilder.makeLiteral(value,
+                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.BOOLEAN,
newCall.getType().isNullable()), false);
+            }
+            case DATE: {
+              Calendar value = (materializedExpr.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL)
?
+                new DateTime(((NullableDateHolder) output).value, DateTimeZone.UTC).toCalendar(null)
:
+                new DateTime(((DateHolder) output).value, DateTimeZone.UTC).toCalendar(null);
+              return rexBuilder.makeLiteral(value,
+                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.DATE,
newCall.getType().isNullable()), false);
+            }
+            case DECIMAL9: {
+              long value;
+              int scale;
+              if (materializedExpr.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL)
{
+                NullableDecimal9Holder decimal9Out = (NullableDecimal9Holder)output;
+                value = decimal9Out.value;
+                scale = decimal9Out.scale;
+              } else {
+                Decimal9Holder decimal9Out = (Decimal9Holder)output;
+                value = decimal9Out.value;
+                scale = decimal9Out.scale;
+              }
+              return rexBuilder.makeLiteral(
+                new BigDecimal(BigInteger.valueOf(value), scale),
                 TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.DECIMAL,
newCall.getType().isNullable()),
-                false));
-            break;
-          case DECIMAL18:
-            reducedValues.add(rexBuilder.makeLiteral(
-                new BigDecimal(BigInteger.valueOf(((Decimal18Holder) output).value), ((Decimal18Holder)output).scale),
+                false);
+            }
+            case DECIMAL18: {
+              long value;
+              int scale;
+              if (materializedExpr.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL)
{
+                NullableDecimal18Holder decimal18Out = (NullableDecimal18Holder)output;
+                value = decimal18Out.value;
+                scale = decimal18Out.scale;
+              } else {
+                Decimal18Holder decimal18Out = (Decimal18Holder)output;
+                value = decimal18Out.value;
+                scale = decimal18Out.scale;
+              }
+              return rexBuilder.makeLiteral(
+                new BigDecimal(BigInteger.valueOf(value), scale),
                 TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.DECIMAL,
newCall.getType().isNullable()),
-                false));
-            break;
-          case DECIMAL28SPARSE:
-            Decimal28SparseHolder decimal28Out = (Decimal28SparseHolder)output;
-            reducedValues.add(rexBuilder.makeLiteral(
-                org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(
-                    decimal28Out.buffer,
-                    decimal28Out.start * 20,
-                    5,
-                    decimal28Out.scale),
+                false);
+            }
+            case DECIMAL28SPARSE: {
+              DrillBuf buffer;
+              int start;
+              int scale;
+              if (materializedExpr.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL)
{
+                NullableDecimal28SparseHolder decimal28Out = (NullableDecimal28SparseHolder)output;
+                buffer = decimal28Out.buffer;
+                start = decimal28Out.start;
+                scale = decimal28Out.scale;
+              } else {
+                Decimal28SparseHolder decimal28Out = (Decimal28SparseHolder)output;
+                buffer = decimal28Out.buffer;
+                start = decimal28Out.start;
+                scale = decimal28Out.scale;
+              }
+              return rexBuilder.makeLiteral(
+                org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(buffer,
start * 20, 5, scale),
+                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.DECIMAL,
newCall.getType().isNullable()), false);
+            }
+            case DECIMAL38SPARSE: {
+              DrillBuf buffer;
+              int start;
+              int scale;
+              if (materializedExpr.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL)
{
+                NullableDecimal38SparseHolder decimal38Out = (NullableDecimal38SparseHolder)output;
+                buffer = decimal38Out.buffer;
+                start = decimal38Out.start;
+                scale = decimal38Out.scale;
+              } else {
+                Decimal38SparseHolder decimal38Out = (Decimal38SparseHolder)output;
+                buffer = decimal38Out.buffer;
+                start = decimal38Out.start;
+                scale = decimal38Out.scale;
+              }
+              return rexBuilder.makeLiteral(org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(buffer,
start * 24, 6, scale),
                 TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.DECIMAL,
newCall.getType().isNullable()),
-                false
-            ));
-            break;
-          case DECIMAL38SPARSE:
-            Decimal38SparseHolder decimal38Out = (Decimal38SparseHolder)output;
-            reducedValues.add(rexBuilder.makeLiteral(
-                org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(
-                    decimal38Out.buffer,
-                    decimal38Out.start * 24,
-                    6,
-                    decimal38Out.scale),
-                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.DECIMAL,
newCall.getType().isNullable()),
-                false));
-            break;
-
-          case TIME:
-            reducedValues.add(rexBuilder.makeLiteral(
-                new DateTime(((TimeHolder)output).value, DateTimeZone.UTC).toCalendar(null),
-                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.TIME,
newCall.getType().isNullable()),
-                false));
-            break;
-          case TIMESTAMP:
-            reducedValues.add(rexBuilder.makeTimestampLiteral(
-                new DateTime(((TimeStampHolder)output).value, DateTimeZone.UTC).toCalendar(null),
0));
-            break;
-          case INTERVALYEAR:
-            reducedValues.add(rexBuilder.makeLiteral(
-                new BigDecimal(((IntervalYearHolder)output).value),
-                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.INTERVAL_YEAR_MONTH,
newCall.getType().isNullable()),
-                false));
-            break;
-          case INTERVALDAY:
-            IntervalDayHolder intervalDayOut = (IntervalDayHolder) output;
-            reducedValues.add(rexBuilder.makeLiteral(
-                new BigDecimal(intervalDayOut.days * DateUtility.daysToStandardMillis + intervalDayOut.milliseconds),
+                false);
+            }
+            case TIME: {
+              Calendar value = (materializedExpr.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL)
?
+                new DateTime(((NullableTimeHolder) output).value, DateTimeZone.UTC).toCalendar(null)
:
+                new DateTime(((TimeHolder) output).value, DateTimeZone.UTC).toCalendar(null);
+              return rexBuilder.makeLiteral(value,
+                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.TIME,
newCall.getType().isNullable()), false);
+            }
+            case TIMESTAMP: {
+              Calendar value = (materializedExpr.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL)
?
+                new DateTime(((NullableTimeStampHolder) output).value, DateTimeZone.UTC).toCalendar(null)
:
+                new DateTime(((TimeStampHolder) output).value, DateTimeZone.UTC).toCalendar(null);
+              return rexBuilder.makeTimestampLiteral(value, 0);
+            }
+            case INTERVALYEAR: {
+              BigDecimal value = (materializedExpr.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL)
?
+                new BigDecimal(((NullableIntervalYearHolder) output).value) :
+                new BigDecimal(((IntervalYearHolder) output).value);
+              return rexBuilder.makeLiteral(value,
+                TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.INTERVAL_YEAR_MONTH,
newCall.getType().isNullable()), false);
+            }
+            case INTERVALDAY: {
+              int days;
+              int milliseconds;
+              if (materializedExpr.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL)
{
+                NullableIntervalDayHolder intervalDayOut = (NullableIntervalDayHolder) output;
+                days = intervalDayOut.days;
+                milliseconds = intervalDayOut.milliseconds;
+              } else {
+                IntervalDayHolder intervalDayOut = (IntervalDayHolder) output;
+                days = intervalDayOut.days;
+                milliseconds = intervalDayOut.milliseconds;
+              }
+              return rexBuilder.makeLiteral(
+                new BigDecimal(days * DateUtility.daysToStandardMillis + milliseconds),
                 TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.INTERVAL_DAY_TIME,
newCall.getType().isNullable()),
-                false));
-            break;
-          // The list of known unsupported types is used to trigger this behavior of re-using
the input expression
-          // before the expression is even attempted to be evaluated, this is just here as
a last precaution a
-          // as new types may be added in the future.
-          default:
-            logger.debug("Constant expression not folded due to return type {}, complete
expression: {}",
+                false);
+            }
+            // The list of known unsupported types is used to trigger this behavior of re-using
the input expression
+            // before the expression is even attempted to be evaluated, this is just here
as a last precaution a
+            // as new types may be added in the future.
+            default:
+              logger.debug("Constant expression not folded due to return type {}, complete
expression: {}",
                 materializedExpr.getMajorType(),
                 ExpressionStringBuilder.toString(materializedExpr));
-            reducedValues.add(newCall);
-            break;
+              return newCall;
+          }
         }
+      };
+
+      reducedValues.add(literator.apply(output));
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/1375a006/exec/java-exec/src/test/java/org/apache/drill/exec/planner/logical/TestCaseNullableTypes.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/planner/logical/TestCaseNullableTypes.java
b/exec/java-exec/src/test/java/org/apache/drill/exec/planner/logical/TestCaseNullableTypes.java
new file mode 100644
index 0000000..8e5245f
--- /dev/null
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/planner/logical/TestCaseNullableTypes.java
@@ -0,0 +1,127 @@
+/*
+* 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.drill.exec.planner.logical;
+
+import org.apache.drill.BaseTestQuery;
+import org.junit.Test;
+
+/**
+ * DRILL-4906
+ * Tests for handling nullable types in CASE function
+ */
+public class TestCaseNullableTypes extends BaseTestQuery {
+
+  @Test
+  public void testCaseNullableTypesInt() throws Exception {
+    testBuilder()
+        .sqlQuery("select (case when (false) then null else 1 end) res1 from (values(1))")
+        .unOrdered()
+        .baselineColumns("res1")
+        .baselineValues(1)
+        .go();
+  }
+
+  @Test
+  public void testCaseNullableTypesVarchar() throws Exception {
+    testBuilder()
+        .sqlQuery("select (res1 = 'qwe') res2 from (select (case when (false) then null else
'qwe' end) res1 from (values(1)))")
+        .unOrdered()
+        .baselineColumns("res2")
+        .baselineValues(true)
+        .go();
+  }
+
+  @Test
+  public void testCaseNullableTypesBigint() throws Exception {
+    testBuilder()
+        .sqlQuery("select (case when (false) then null else " + Long.MAX_VALUE + " end) res1
from (values(1))")
+        .unOrdered()
+        .baselineColumns("res1")
+        .baselineValues(Long.MAX_VALUE)
+        .go();
+  }
+
+  @Test
+  public void testCaseNullableTypesFloat() throws Exception {
+    testBuilder()
+        .sqlQuery("select (case when (false) then null else cast(0.1 as float) end) res1
from (values(1))")
+        .unOrdered()
+        .baselineColumns("res1")
+        .baselineValues(0.1F)
+        .go();
+  }
+
+  @Test
+  public void testCaseNullableTypesDouble() throws Exception {
+    testBuilder()
+        .sqlQuery("select (case when (false) then null else cast(0.1 as double) end) res1
from (values(1))")
+        .unOrdered()
+        .baselineColumns("res1")
+        .baselineValues(0.1)
+        .go();
+  }
+
+  @Test
+  public void testCaseNullableTypesBoolean() throws Exception {
+    testBuilder()
+        .sqlQuery("select (case when (false) then null else true end) res1 from (values(1))")
+        .unOrdered()
+        .baselineColumns("res1")
+        .baselineValues(true)
+        .go();
+  }
+
+  @Test
+  public void testCaseNullableTypesDate() throws Exception {
+    testBuilder()
+        .sqlQuery("select (res1 = 22/09/2016) res2 from (select (case when (false) then null
else 22/09/2016 end) res1 from (values(1)))")
+        .unOrdered()
+        .baselineColumns("res2")
+        .baselineValues(true)
+        .go();
+  }
+
+  @Test
+  public void testCaseNullableTypesTimestamp() throws Exception {
+    testBuilder()
+        .sqlQuery("select (res1 = current_timestamp) res2 from (select (case when (false)
then null else current_timestamp end) res1 from (values(1)))")
+        .unOrdered()
+        .baselineColumns("res2")
+        .baselineValues(true)
+        .go();
+  }
+
+  @Test
+  public void testNestedCaseNullableTypes() throws Exception {
+    testBuilder()
+      .sqlQuery("select (case when (false) then null else (case when (false) then null else
cast(0.1 as float) end) end) res1 from (values(1))")
+      .unOrdered()
+      .baselineColumns("res1")
+      .baselineValues(0.1f)
+      .go();
+  }
+
+  @Test
+  public void testMultipleCasesNullableTypes() throws Exception {
+    testBuilder()
+      .sqlQuery("select (case when (false) then null else 1 end) res1, (case when (false)
then null else cast(0.1 as float) end) res2 from (values(1))")
+      .unOrdered()
+      .baselineColumns("res1", "res2")
+      .baselineValues(1, 0.1f)
+      .go();
+  }
+}


Mime
View raw message