From e477209fe12263f3b70e8be9e733dbc0054b4b7e Mon Sep 17 00:00:00 2001 From: kyotoYaho Date: Tue, 19 Mar 2019 17:45:54 +0800 Subject: [PATCH] KYLIN-3881 make then expression combined with its condition --- .../adapter/enumerable/RexImpTable.java | 5 ++- .../enumerable/RexToLixTranslator.java | 34 +++++++++++++++++++ .../calcite/linq4j/tree/BlockBuilder.java | 8 +++++ 3 files changed, 46 insertions(+), 1 deletion(-) 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 a1a88ad64..154a6fad5 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 @@ -2110,7 +2110,10 @@ private Expression implementRecurse(RexToLixTranslator translator, return ifTrue == null || ifFalse == null ? Util.first(ifTrue, ifFalse) - : Expressions.condition(test, ifTrue, ifFalse); + // : Expressions.condition(test, ifTrue, ifFalse); + // the expression behind then should not be isolated with its condition, + // otherwise exceptions may happen, like Division Undefined + : Expressions.condition(test, translator.translateToInit(ifTrue), translator.translateToInit(ifFalse)); } } } 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 083df7c62..ecffe2f08 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 @@ -16,16 +16,20 @@ */ package org.apache.calcite.adapter.enumerable; +import com.google.common.base.Function; +import com.google.common.collect.Lists; import org.apache.calcite.DataContext; import org.apache.calcite.adapter.java.JavaTypeFactory; import org.apache.calcite.avatica.util.ByteString; import org.apache.calcite.avatica.util.DateTimeUtils; import org.apache.calcite.linq4j.function.Function1; +import org.apache.calcite.linq4j.tree.BinaryExpression; import org.apache.calcite.linq4j.tree.BlockBuilder; import org.apache.calcite.linq4j.tree.ConstantExpression; import org.apache.calcite.linq4j.tree.Expression; import org.apache.calcite.linq4j.tree.ExpressionType; import org.apache.calcite.linq4j.tree.Expressions; +import org.apache.calcite.linq4j.tree.MethodCallExpression; import org.apache.calcite.linq4j.tree.ParameterExpression; import org.apache.calcite.linq4j.tree.Primitive; import org.apache.calcite.linq4j.tree.UnaryExpression; @@ -53,6 +57,7 @@ import com.google.common.collect.ImmutableMap; +import javax.annotation.Nullable; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; @@ -1256,6 +1261,35 @@ public Expression getRoot() { return root; } + public Expression translateToInit(Expression expr) { + return translateToInit(list.getParameterExpressionMap(), expr); + } + + /** + * get the initial expression of parameter expression started with 'v' + * */ + private Expression translateToInit(final Map paramExprMap, Expression expr) { + Expression result = expr; + if (expr instanceof ParameterExpression && expr.toString().startsWith("v") && paramExprMap.containsKey(expr)) { + result = translateToInit(paramExprMap, paramExprMap.get(expr)); + } else if (expr instanceof BinaryExpression) { + BinaryExpression biExpr = (BinaryExpression) expr; + Expression expr0 = translateToInit(paramExprMap, biExpr.expression0); + Expression expr1 = translateToInit(paramExprMap, biExpr.expression1); + result = Expressions.makeBinary(biExpr.nodeType, expr0, expr1); + } else if (expr instanceof MethodCallExpression) { + List innerExprs = Lists.transform(((MethodCallExpression) expr).expressions, new Function() { + @Nullable + @Override + public Expression apply(@Nullable Expression input) { + return translateToInit(paramExprMap, input); + } + }); + result = Expressions.call(((MethodCallExpression) expr).method, innerExprs); + } + return result; + } + /** Translates a field of an input to an expression. */ public interface InputGetter { Expression field(BlockBuilder list, int index, Type storageType); diff --git a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BlockBuilder.java b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BlockBuilder.java index 653ae2363..d6f3552cb 100644 --- a/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BlockBuilder.java +++ b/linq4j/src/main/java/org/apache/calcite/linq4j/tree/BlockBuilder.java @@ -71,6 +71,14 @@ public BlockBuilder(boolean optimizing, BlockBuilder parent) { this.parent = parent; } + public Map getParameterExpressionMap() { + Map result = new HashMap<>(); + for(DeclarationStatement dState : expressionForReuse.values()) { + result.put(dState.parameter, dState.initializer); + } + return result; + } + /** * Clears this BlockBuilder. */ -- 2.19.2