You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by mb...@apache.org on 2018/08/31 20:20:34 UTC

[10/16] asterixdb git commit: [ASTERIXDB-2447][COMP] Parameter rewriting for if_missing, if_null functions

[ASTERIXDB-2447][COMP] Parameter rewriting for if_missing, if_null functions

- user model changes: no
- storage format changes: no
- interface changes: no

Details:
- Introduce cast operation for parameters of if_missing, if_null functions
  (as performed for parameters of the switch_case function)
- Fix union type handling in TypeResolverUtil.generalizeTypes()

Change-Id: I768d8236f5b0ccb9a850304ffedd3686d911702d
Reviewed-on: https://asterix-gerrit.ics.uci.edu/2935
Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
Reviewed-by: Till Westmann <ti...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/8c88975a
Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/8c88975a
Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/8c88975a

Branch: refs/heads/master
Commit: 8c88975a781cd2b384da31bcd59aad2e26480e3e
Parents: 9963a91
Author: Dmitry Lychagin <dm...@couchbase.com>
Authored: Tue Aug 28 16:32:42 2018 -0700
Committer: Dmitry Lychagin <dm...@couchbase.com>
Committed: Thu Aug 30 17:31:14 2018 -0700

----------------------------------------------------------------------
 .../rules/InjectTypeCastForSwitchCaseRule.java  | 71 +++++++++++++++-----
 .../ifmissing/ifmissing.1.query.sqlpp           |  7 ++
 .../ifmissingornull.1.query.sqlpp               |  7 ++
 .../null-missing/ifnull/ifnull.1.query.sqlpp    |  7 ++
 .../null-missing/ifmissing/ifmissing.1.adm      |  2 +-
 .../ifmissingornull/ifmissingornull.1.adm       |  2 +-
 .../results/null-missing/ifnull/ifnull.1.adm    |  2 +-
 .../dataflow/data/common/TypeResolverUtil.java  |  2 +-
 8 files changed, 81 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8c88975a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForSwitchCaseRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForSwitchCaseRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForSwitchCaseRule.java
index fa9385a..683d29f 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForSwitchCaseRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForSwitchCaseRule.java
@@ -22,6 +22,7 @@ package org.apache.asterix.optimizer.rules;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.asterix.dataflow.data.common.TypeResolverUtil;
 import org.apache.asterix.lang.common.util.FunctionUtil;
@@ -38,14 +39,23 @@ import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
 import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
 import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
 
+import com.google.common.collect.ImmutableSet;
+
 /**
- * This rule injects cast functions for "THEN" and "ELSE" branches of a switch-case function if
- * different "THEN" and "ELSE" branches have heterogeneous return types.
+ * This rule injects casts for function parameters if they have heterogeneous return types:
+ * <ul>
+ *     <li>for "THEN" and "ELSE" branches of a switch-case function</li>
+ *     <li>for parameters of "if missing/null" functions  (if-missing(), if-null(), if-missing-or-null())</li>
+ * </ul>
  */
 public class InjectTypeCastForSwitchCaseRule implements IAlgebraicRewriteRule {
 
+    private static final Set<FunctionIdentifier> IF_FUNCTIONS =
+            ImmutableSet.of(BuiltinFunctions.IF_MISSING, BuiltinFunctions.IF_NULL, BuiltinFunctions.IF_MISSING_OR_NULL);
+
     @Override
     public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
             throws AlgebricksException {
@@ -80,10 +90,17 @@ public class InjectTypeCastForSwitchCaseRule implements IAlgebraicRewriteRule {
                 rewritten = true;
             }
         }
-        if (!func.getFunctionIdentifier().equals(BuiltinFunctions.SWITCH_CASE)) {
-            return rewritten;
+        FunctionIdentifier funcId = func.getFunctionIdentifier();
+        if (funcId.equals(BuiltinFunctions.SWITCH_CASE)) {
+            if (rewriteSwitchCase(op, func, context)) {
+                rewritten = true;
+            }
+        } else if (IF_FUNCTIONS.contains(funcId)) {
+            if (rewriteFunction(op, func, context)) {
+                rewritten = true;
+            }
         }
-        return rewriteSwitchCase(op, func, context);
+        return rewritten;
     }
 
     // Injects casts that cast types for different "THEN" and "ELSE" branches.
@@ -96,20 +113,44 @@ public class InjectTypeCastForSwitchCaseRule implements IAlgebraicRewriteRule {
         boolean rewritten = false;
         for (int argIndex = 2; argIndex < argSize; argIndex += (argIndex + 2 == argSize) ? 1 : 2) {
             Mutable<ILogicalExpression> argRef = argRefs.get(argIndex);
-            IAType type = (IAType) env.getType(argRefs.get(argIndex).getValue());
-            if (TypeResolverUtil.needsCast(producedType, type)) {
-                ILogicalExpression argExpr = argRef.getValue();
-                // Injects a cast call to cast the data type to the produced type of the switch-case function call.
-                ScalarFunctionCallExpression castFunc =
-                        new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.CAST_TYPE),
-                                new ArrayList<>(Collections.singletonList(new MutableObject<>(argExpr))));
-                castFunc.setSourceLocation(argExpr.getSourceLocation());
-                TypeCastUtils.setRequiredAndInputTypes(castFunc, producedType, type);
-                argRef.setValue(castFunc);
+            if (rewriteFunctionArgument(argRef, producedType, env)) {
+                rewritten = true;
+            }
+        }
+        return rewritten;
+    }
+
+    // Injects casts that cast types for all function parameters
+    private boolean rewriteFunction(ILogicalOperator op, AbstractFunctionCallExpression func,
+            IOptimizationContext context) throws AlgebricksException {
+        IVariableTypeEnvironment env = op.computeInputTypeEnvironment(context);
+        IAType producedType = (IAType) env.getType(func);
+        List<Mutable<ILogicalExpression>> argRefs = func.getArguments();
+        int argSize = argRefs.size();
+        boolean rewritten = false;
+        for (int argIndex = 0; argIndex < argSize; argIndex++) {
+            Mutable<ILogicalExpression> argRef = argRefs.get(argIndex);
+            if (rewriteFunctionArgument(argRef, producedType, env)) {
                 rewritten = true;
             }
         }
         return rewritten;
     }
 
+    private boolean rewriteFunctionArgument(Mutable<ILogicalExpression> argRef, IAType funcOutputType,
+            IVariableTypeEnvironment env) throws AlgebricksException {
+        ILogicalExpression argExpr = argRef.getValue();
+        IAType type = (IAType) env.getType(argExpr);
+        if (TypeResolverUtil.needsCast(funcOutputType, type)) {
+            // Injects a cast call to cast the data type to the produced type of the function call.
+            ScalarFunctionCallExpression castFunc =
+                    new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.CAST_TYPE),
+                            new ArrayList<>(Collections.singletonList(new MutableObject<>(argExpr))));
+            castFunc.setSourceLocation(argExpr.getSourceLocation());
+            TypeCastUtils.setRequiredAndInputTypes(castFunc, funcOutputType, type);
+            argRef.setValue(castFunc);
+            return true;
+        }
+        return false;
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8c88975a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissing/ifmissing.1.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissing/ifmissing.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissing/ifmissing.1.query.sqlpp
index 2f0d837..0abb997 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissing/ifmissing.1.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissing/ifmissing.1.query.sqlpp
@@ -29,5 +29,12 @@
             missing,
             case when get_year(current_datetime()) > 0 then missing else false end,
             case when get_year(current_datetime()) > 0 then true else null end
+        ),
+   "j": (
+            let v = if_missing(
+                case when get_year(current_datetime()) > 0 then missing else false end,
+                { "c": [ 2 ] }
+            )
+            select v as b
         )
 };

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8c88975a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissingornull/ifmissingornull.1.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissingornull/ifmissingornull.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissingornull/ifmissingornull.1.query.sqlpp
index 32f040f..22a8acd 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissingornull/ifmissingornull.1.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissingornull/ifmissingornull.1.query.sqlpp
@@ -32,5 +32,12 @@
             case when get_year(current_datetime()) > 0 then missing else false end,
             case when get_year(current_datetime()) > 0 then null else false end,
             case when get_year(current_datetime()) > 0 then true else missing end
+        ),
+   "j": (
+            let v = if_missing_or_null(
+                case when get_year(current_datetime()) > 0 then missing else false end,
+                { "c": [ 2 ] }
+            )
+            select v as b
         )
 };
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8c88975a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifnull/ifnull.1.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifnull/ifnull.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifnull/ifnull.1.query.sqlpp
index c0683bd..0121cd8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifnull/ifnull.1.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifnull/ifnull.1.query.sqlpp
@@ -30,5 +30,12 @@
             null,
             case when get_year(current_datetime()) > 0 then null else false end,
             case when get_year(current_datetime()) > 0 then true else missing end
+        ),
+   "j": (
+            let v = if_null(
+                case when get_year(current_datetime()) > 0 then null else false end,
+                { "c": [ 2 ] }
+            )
+            select v as b
         )
 };

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8c88975a/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissing/ifmissing.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissing/ifmissing.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissing/ifmissing.1.adm
index 0a2275f..14620a1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissing/ifmissing.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissing/ifmissing.1.adm
@@ -1 +1 @@
-{ "a": true, "b": true, "c": true, "d": true, "e": true, "f": true, "g": true, "i": true }
\ No newline at end of file
+{ "a": true, "b": true, "c": true, "d": true, "e": true, "f": true, "g": true, "i": true, "j": [ { "b": { "c": [ 2 ] } } ] }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8c88975a/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissingornull/ifmissingornull.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissingornull/ifmissingornull.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissingornull/ifmissingornull.1.adm
index 633c503..eff2651 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissingornull/ifmissingornull.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissingornull/ifmissingornull.1.adm
@@ -1 +1 @@
-{ "a": true, "b": true, "c": true, "d": true, "e": true, "f": true, "g": true, "h": true, "i": true }
\ No newline at end of file
+{ "a": true, "b": true, "c": true, "d": true, "e": true, "f": true, "g": true, "h": true, "i": true, "j": [ { "b": { "c": [ 2 ] } } ] }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8c88975a/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifnull/ifnull.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifnull/ifnull.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifnull/ifnull.1.adm
index 633c503..eff2651 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifnull/ifnull.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifnull/ifnull.1.adm
@@ -1 +1 @@
-{ "a": true, "b": true, "c": true, "d": true, "e": true, "f": true, "g": true, "h": true, "i": true }
\ No newline at end of file
+{ "a": true, "b": true, "c": true, "d": true, "e": true, "f": true, "g": true, "h": true, "i": true, "j": [ { "b": { "c": [ 2 ] } } ] }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/8c88975a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/TypeResolverUtil.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/TypeResolverUtil.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/TypeResolverUtil.java
index 561df5e..b7bd8ca 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/TypeResolverUtil.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/TypeResolverUtil.java
@@ -106,7 +106,7 @@ public class TypeResolverUtil {
         // Gets the actual types for UNIONs and mark unknownable to be true.
         if (leftTypeTag == ATypeTag.UNION || rightTypeTag == ATypeTag.UNION) {
             leftType = TypeComputeUtils.getActualType(leftType);
-            rightType = TypeComputeUtils.getActualType(leftType);
+            rightType = TypeComputeUtils.getActualType(rightType);
             leftTypeTag = leftType.getTypeTag();
             rightTypeTag = rightType.getTypeTag();
             unknownable = true;