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();
+ }
+}
|