[CALCITE-2596] When translating correlated variables in enumerable convention, convert not-null boxed primitive values to primitive (Stamatis Zampetakis)
Apply nullAs policy when translating expressions with correlated variables. Close apache/calcite#868 Project: http://git-wip-us.apache.org/repos/asf/calcite/repo Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/5c6d3c22 Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/5c6d3c22 Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/5c6d3c22 Branch: refs/heads/master Commit: 5c6d3c22cd77e3fd6427f327187b3e0bfd8a2a81 Parents: 0ad68c3 Author: Stamatis Zampetakis <[email protected]> Authored: Wed Sep 26 14:03:29 2018 +0200 Committer: Julian Hyde <[email protected]> Committed: Mon Dec 3 19:16:15 2018 -0800 ---------------------------------------------------------------------- .../adapter/enumerable/RexToLixTranslator.java | 30 +++++++++++++------- .../enumerable/EnumerableCorrelateTest.java | 12 ++++++++ 2 files changed, 32 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/calcite/blob/5c6d3c22/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java index e28a8d0..1a63068 100644 --- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java +++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java @@ -571,6 +571,18 @@ public class RexToLixTranslator { return scaleIntervalToNumber(sourceType, targetType, convert); } + private Expression handleNullUnboxingIfNecessary( + Expression input, + RexImpTable.NullAs nullAs, + Type storageType) { + if (RexImpTable.NullAs.NOT_POSSIBLE == nullAs && input.type.equals(storageType)) { + // When we asked for not null input that would be stored as box, avoid + // unboxing which may occur in the handleNull method below. + return input; + } + return handleNull(input, nullAs); + } + /** Adapts an expression with "normal" result to one that adheres to * this particular policy. Wraps the result expression into a new * parameter if need be. @@ -624,18 +636,13 @@ public class RexToLixTranslator { nullAs = RexImpTable.NullAs.NOT_POSSIBLE; } switch (expr.getKind()) { - case INPUT_REF: + case INPUT_REF: { final int index = ((RexInputRef) expr).getIndex(); Expression x = inputGetter.field(list, index, storageType); Expression input = list.append("inp" + index + "_", x); // safe to share - if (nullAs == RexImpTable.NullAs.NOT_POSSIBLE - && input.type.equals(storageType)) { - // When we asked for not null input that would be stored as box, avoid - // unboxing via nullAs.handle below. - return input; - } - return handleNull(input, nullAs); + return handleNullUnboxingIfNecessary(input, nullAs, storageType); + } case LOCAL_REF: return translate( deref(expr), @@ -655,7 +662,7 @@ public class RexToLixTranslator { case CORREL_VARIABLE: throw new RuntimeException("Cannot translate " + expr + ". Correlated" + " variables should always be referenced by field access"); - case FIELD_ACCESS: + case FIELD_ACCESS: { RexFieldAccess fieldAccess = (RexFieldAccess) expr; RexNode target = deref(fieldAccess.getReferenceExpr()); int fieldIndex = fieldAccess.getField().getIndex(); @@ -668,7 +675,9 @@ public class RexToLixTranslator { } InputGetter getter = correlates.apply(((RexCorrelVariable) target).getName()); - return getter.field(list, fieldIndex, storageType); + Expression y = getter.field(list, fieldIndex, storageType); + Expression input = list.append("corInp" + fieldIndex + "_", y); // safe to share + return handleNullUnboxingIfNecessary(input, nullAs, storageType); default: RexNode rxIndex = builder.makeLiteral(fieldIndex, typeFactory.createType(int.class), true); RexNode rxName = builder.makeLiteral(fieldName, typeFactory.createType(String.class), true); @@ -678,6 +687,7 @@ public class RexToLixTranslator { ImmutableList.of(target, rxIndex, rxName)); return translateCall(accessCall, nullAs); } + } default: if (expr instanceof RexCall) { return translateCall((RexCall) expr, nullAs); http://git-wip-us.apache.org/repos/asf/calcite/blob/5c6d3c22/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableCorrelateTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableCorrelateTest.java b/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableCorrelateTest.java index 2edc6b9..876c18f 100644 --- a/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableCorrelateTest.java +++ b/core/src/test/java/org/apache/calcite/test/enumerable/EnumerableCorrelateTest.java @@ -95,6 +95,18 @@ public class EnumerableCorrelateTest { "empid=150; name=Sebastian"); } + @Test public void simpleCorrelateWithConditionIncludingBoxedPrimitive() { + final String sql = "select empid from emps e where not exists (\n" + + " select 1 from depts d where d.deptno=e.commission)"; + tester(false, new JdbcTest.HrSchema()) + .query(sql) + .returnsUnordered( + "empid=100", + "empid=110", + "empid=150", + "empid=200"); + } + private CalciteAssert.AssertThat tester(boolean forceDecorrelate, Object schema) { return CalciteAssert.that()
