You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by bu...@apache.org on 2016/09/21 05:48:55 UTC

asterixdb git commit: ASTERIXDB-1631: let TypeComputeUtils handle input type ANY properly.

Repository: asterixdb
Updated Branches:
  refs/heads/master bc3f9b2f0 -> 2816885d1


ASTERIXDB-1631: let TypeComputeUtils handle input type ANY properly.

Change-Id: Ie6b3f0e9d9b4ddd9280e06f72a5ca30aa776315d
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1191
Sonar-Qube: Jenkins <je...@fulliautomatix.ics.uci.edu>
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/2816885d
Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/2816885d
Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/2816885d

Branch: refs/heads/master
Commit: 2816885d1a4a2efd969df78abc0b735e40f65a38
Parents: bc3f9b2
Author: Yingyi Bu <yi...@couchbase.com>
Authored: Tue Sep 20 18:48:15 2016 -0700
Committer: Yingyi Bu <bu...@gmail.com>
Committed: Tue Sep 20 22:48:29 2016 -0700

----------------------------------------------------------------------
 asterixdb/asterix-om/pom.xml                    |   6 +
 .../om/functions/AsterixBuiltinFunctions.java   |   4 +-
 .../impl/FlowRecordResultTypeComputer.java      |  45 -------
 .../impl/NotMissingTypeComputer.java            |  77 ------------
 .../impl/NotUnknownTypeComputer.java            |  53 +++++++++
 .../impl/NullableDoubleTypeComputer.java        |   2 +-
 .../impl/RecordAddFieldsTypeComputer.java       |   4 +-
 .../impl/SubsetCollectionTypeComputer.java      |   3 +
 .../om/typecomputer/impl/TypeComputeUtils.java  |  35 ++++--
 .../om/typecomputer/TypeComputerTest.java       | 116 +++++++++++++++++++
 10 files changed, 206 insertions(+), 139 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/pom.xml
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/pom.xml b/asterixdb/asterix-om/pom.xml
index 60fa26c..72bf65e 100644
--- a/asterixdb/asterix-om/pom.xml
+++ b/asterixdb/asterix-om/pom.xml
@@ -74,5 +74,11 @@
       <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <version>1.10.19</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java
index 184dd84..a85d33b 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java
@@ -68,7 +68,7 @@ import org.apache.asterix.om.typecomputer.impl.InjectFailureTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.LocalAvgTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.MinMaxAggTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.NonTaggedGetItemResultType;
-import org.apache.asterix.om.typecomputer.impl.NotMissingTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.NotUnknownTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.NullableDoubleTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.NumericAddSubMulDivTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.NumericAggTypeComputer;
@@ -810,7 +810,7 @@ public class AsterixBuiltinFunctions {
         addFunction(DEEP_EQUAL, BooleanFunctionTypeComputer.INSTANCE, true);
 
         // and then, Asterix builtin functions
-        addPrivateFunction(CHECK_UNKNOWN, NotMissingTypeComputer.INSTANCE, true);
+        addPrivateFunction(CHECK_UNKNOWN, NotUnknownTypeComputer.INSTANCE, true);
         addPrivateFunction(ANY_COLLECTION_MEMBER, CollectionMemberResultType.INSTANCE, true);
         addFunction(BOOLEAN_CONSTRUCTOR, StringBooleanTypeComputer.INSTANCE, true);
         addFunction(CARET, NumericAddSubMulDivTypeComputer.INSTANCE, true);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/FlowRecordResultTypeComputer.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/FlowRecordResultTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/FlowRecordResultTypeComputer.java
deleted file mode 100644
index 27e8a3d..0000000
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/FlowRecordResultTypeComputer.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.asterix.om.typecomputer.impl;
-
-import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
-import org.apache.asterix.om.typecomputer.base.TypeCastUtils;
-import org.apache.asterix.om.types.IAType;
-import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
-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.metadata.IMetadataProvider;
-
-public class FlowRecordResultTypeComputer implements IResultTypeComputer {
-
-    public static final FlowRecordResultTypeComputer INSTANCE = new FlowRecordResultTypeComputer();
-
-    @Override
-    public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env,
-            IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
-        ScalarFunctionCallExpression funcExpr = (ScalarFunctionCallExpression) expression;
-        IAType type = TypeCastUtils.getRequiredType(funcExpr);
-        if (type == null) {
-            type = (IAType) env.getType(funcExpr.getArguments().get(0).getValue());
-        }
-        return type;
-    }
-}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NotMissingTypeComputer.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NotMissingTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NotMissingTypeComputer.java
deleted file mode 100644
index 68444c4..0000000
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NotMissingTypeComputer.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.asterix.om.typecomputer.impl;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
-import org.apache.asterix.om.types.ATypeTag;
-import org.apache.asterix.om.types.AUnionType;
-import org.apache.asterix.om.types.IAType;
-import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
-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.metadata.IMetadataProvider;
-
-/**
- * This class is the type computer for not-missing function.
- * If the input type is not a union, we just return it.
- * If the input type is a union,
- * case 1: we return a new union without missing if the new union still has more than one types;
- * case 2: we return the non-missing item type in the original union if there are only missing
- * and it in the original union.
- */
-public class NotMissingTypeComputer implements IResultTypeComputer {
-
-    public static final NotMissingTypeComputer INSTANCE = new NotMissingTypeComputer();
-
-    @Override
-    public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env,
-            IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
-        AbstractFunctionCallExpression f = (AbstractFunctionCallExpression) expression;
-        IAType type = (IAType) env.getType(f.getArguments().get(0).getValue());
-        if (type.getTypeTag() != ATypeTag.UNION) {
-            // directly return the input type if it is not a union
-            return type;
-        }
-
-        AUnionType unionType = (AUnionType) type;
-        List<IAType> items = new ArrayList<>();
-        // copy the item types
-        items.addAll(unionType.getUnionList());
-
-        // remove missing
-        for (int i = items.size() - 1; i >= 0; i--) {
-            IAType itemType = items.get(i);
-            if (itemType.getTypeTag() == ATypeTag.MISSING) {
-                items.remove(i);
-            }
-        }
-        if (items.size() == 1) {
-            //only one type is left
-            return items.get(0);
-        } else {
-            //more than two types are left
-            return new AUnionType(items, unionType.getTypeName());
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NotUnknownTypeComputer.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NotUnknownTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NotUnknownTypeComputer.java
new file mode 100644
index 0000000..163ff30
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NotUnknownTypeComputer.java
@@ -0,0 +1,53 @@
+/*
+ * 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.asterix.om.typecomputer.impl;
+
+import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AUnionType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+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.metadata.IMetadataProvider;
+
+/**
+ * This class is the type computer for check-unknown function.
+ * If the input type is not a union, we just return it.
+ * If the input type is a union, we return the actual, non-null/non-missing type.
+ */
+public class NotUnknownTypeComputer implements IResultTypeComputer {
+
+    public static final NotUnknownTypeComputer INSTANCE = new NotUnknownTypeComputer();
+
+    @Override
+    public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env,
+            IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
+        AbstractFunctionCallExpression f = (AbstractFunctionCallExpression) expression;
+        IAType type = (IAType) env.getType(f.getArguments().get(0).getValue());
+        if (type.getTypeTag() != ATypeTag.UNION) {
+            // directly return the input type if it is not a union
+            return type;
+        }
+        AUnionType unionType = (AUnionType) type;
+        return unionType.getActualType();
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NullableDoubleTypeComputer.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NullableDoubleTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NullableDoubleTypeComputer.java
index 94c75d2..be3138d 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NullableDoubleTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NullableDoubleTypeComputer.java
@@ -37,6 +37,6 @@ public class NullableDoubleTypeComputer implements IResultTypeComputer {
     @Override
     public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env,
             IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
-        return AUnionType.createMissableType(BuiltinType.ADOUBLE, "OptionalDouble");
+        return AUnionType.createNullableType(BuiltinType.ADOUBLE, "OptionalDouble");
     }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordAddFieldsTypeComputer.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordAddFieldsTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordAddFieldsTypeComputer.java
index 289db7c..6d29c36 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordAddFieldsTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/RecordAddFieldsTypeComputer.java
@@ -40,7 +40,6 @@ import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 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.AbstractLogicalExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
 import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
 
@@ -56,7 +55,6 @@ public class RecordAddFieldsTypeComputer implements IResultTypeComputer {
     @Override
     public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env,
             IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
-
         AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expression;
         IAType type0 = (IAType) env.getType(funcExpr.getArguments().get(0).getValue());
 
@@ -65,7 +63,7 @@ public class RecordAddFieldsTypeComputer implements IResultTypeComputer {
             throw new AlgebricksException("Input record cannot be null");
         }
 
-        AbstractLogicalExpression arg1 = (AbstractLogicalExpression) funcExpr.getArguments().get(1).getValue();
+        ILogicalExpression arg1 = funcExpr.getArguments().get(1).getValue();
         IAType type1 = (IAType) env.getType(arg1);
         AOrderedListType inputOrderedListType = TypeComputeUtils.extractOrderedListType(type1);
         if (inputOrderedListType == null) {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubsetCollectionTypeComputer.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubsetCollectionTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubsetCollectionTypeComputer.java
index 40c57a4..3fcb9bb 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubsetCollectionTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubsetCollectionTypeComputer.java
@@ -22,6 +22,7 @@ import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
 import org.apache.asterix.om.types.ATypeTag;
 import org.apache.asterix.om.types.AUnionType;
 import org.apache.asterix.om.types.AbstractCollectionType;
+import org.apache.asterix.om.types.BuiltinType;
 import org.apache.asterix.om.types.IAType;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
@@ -65,6 +66,8 @@ public class SubsetCollectionTypeComputer implements IResultTypeComputer {
                 }
                 throw new AlgebricksException("Expecting collection type. Found " + t);
             }
+            case ANY:
+                return BuiltinType.ANY;
             default: {
                 throw new AlgebricksException("Expecting collection type. Found " + t);
             }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputeUtils.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputeUtils.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputeUtils.java
index 711b840..823f51e 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputeUtils.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputeUtils.java
@@ -111,19 +111,27 @@ public class TypeComputeUtils {
         byte category = CERTAIN;
         boolean meetNull = false;
         for (IAType inputType : inputTypes) {
-            ATypeTag inputTypeTag = inputType.getTypeTag();
-            if (inputTypeTag == ATypeTag.UNION) {
-                AUnionType unionType = (AUnionType) inputType;
-                if (unionType.isNullableType()) {
+            switch (inputType.getTypeTag()) {
+                case UNION:
+                    AUnionType unionType = (AUnionType) inputType;
+                    if (unionType.isNullableType()) {
+                        category |= NULLABLE;
+                    }
+                    if (unionType.isMissableType()) {
+                        category |= MISSABLE;
+                    }
+                    break;
+                case MISSING:
+                    return MISSING;
+                case NULL:
+                    meetNull = true;
+                    break;
+                case ANY:
                     category |= NULLABLE;
-                }
-                if (unionType.isMissableType()) {
                     category |= MISSABLE;
-                }
-            } else if (inputTypeTag == ATypeTag.MISSING) {
-                return MISSING;
-            } else if (inputTypeTag == ATypeTag.NULL) {
-                meetNull = true;
+                    break;
+                default:
+                    break;
             }
         }
         if (meetNull) {
@@ -133,6 +141,9 @@ public class TypeComputeUtils {
     }
 
     private static IAType getResultType(IAType type, byte category) {
+        if (type.getTypeTag() == ATypeTag.ANY) {
+            return type;
+        }
         if (category == CERTAIN) {
             return type;
         }
@@ -185,6 +196,8 @@ public class TypeComputeUtils {
                 } else {
                     return null;
                 }
+            case ANY:
+                return ARecordType.FULLY_OPEN_RECORD_TYPE;
             default:
                 return null;
         }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/2816885d/asterixdb/asterix-om/src/test/java/org/apache/asterix/om/typecomputer/TypeComputerTest.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/test/java/org/apache/asterix/om/typecomputer/TypeComputerTest.java b/asterixdb/asterix-om/src/test/java/org/apache/asterix/om/typecomputer/TypeComputerTest.java
new file mode 100644
index 0000000..760fd18
--- /dev/null
+++ b/asterixdb/asterix-om/src/test/java/org/apache/asterix/om/typecomputer/TypeComputerTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.asterix.om.typecomputer;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AUnionType;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.commons.lang3.mutable.MutableObject;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+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.metadata.IMetadataProvider;
+import org.junit.Assert;
+import org.junit.Test;
+import org.reflections.Reflections;
+import org.reflections.scanners.SubTypesScanner;
+
+// Tests if all type computers can handle input type ANY properly.
+public class TypeComputerTest {
+
+    @Test
+    public void test() throws Exception {
+        // Several exceptional type computers.
+        Set<String> exceptionalTypeComputers = new HashSet<>();
+        exceptionalTypeComputers.add("InjectFailureTypeComputer");
+        exceptionalTypeComputers.add("RecordAddFieldsTypeComputer");
+        exceptionalTypeComputers.add("OpenRecordConstructorResultType");
+        exceptionalTypeComputers.add("RecordRemoveFieldsTypeComputer");
+        exceptionalTypeComputers.add("ClosedRecordConstructorResultType");
+        exceptionalTypeComputers.add("LocalAvgTypeComputer");
+        exceptionalTypeComputers.add("BooleanOnlyTypeComputer");
+        exceptionalTypeComputers.add("AMissingTypeComputer");
+        exceptionalTypeComputers.add("NullableDoubleTypeComputer");
+        exceptionalTypeComputers.add("RecordMergeTypeComputer");
+
+        // Tests all usual type computers.
+        Reflections reflections = new Reflections("org.apache.asterix.om.typecomputer", new SubTypesScanner(false));
+        Set<Class<? extends IResultTypeComputer>> classes = reflections.getSubTypesOf(IResultTypeComputer.class);
+        for (Class<? extends IResultTypeComputer> c : classes) {
+            if (exceptionalTypeComputers.contains(c.getSimpleName()) || Modifier.isAbstract(c.getModifiers())) {
+                continue;
+            }
+            System.out.println("Test type computer: " + c.getName());
+            Assert.assertTrue(testTypeComputer(c));
+        }
+    }
+
+    private boolean testTypeComputer(Class<? extends IResultTypeComputer> c) throws Exception {
+        // Mocks the type environment.
+        IVariableTypeEnvironment mockTypeEnv = mock(IVariableTypeEnvironment.class);
+        // Mocks the metadata provider.
+        IMetadataProvider<?, ?> mockMetadataProvider = mock(IMetadataProvider.class);
+
+        // Mocks function expression.
+        AbstractFunctionCallExpression mockExpr = mock(AbstractFunctionCallExpression.class);
+
+        // A function at most has six argument.
+        List<Mutable<ILogicalExpression>> argRefs = new ArrayList<>();
+        for (int argIndex = 0; argIndex < 6; ++argIndex) {
+            ILogicalExpression mockArg = mock(ILogicalExpression.class);
+            argRefs.add(new MutableObject<>(mockArg));
+            when(mockTypeEnv.getType(mockArg)).thenReturn(BuiltinType.ANY);
+        }
+
+        // Sets up arguments for the mocked expression.
+        when(mockExpr.getArguments()).thenReturn(argRefs);
+
+        // Sets up required/actual types of the mocked expression.
+        Object[] opaqueParameters = new Object[2];
+        opaqueParameters[0] = BuiltinType.ANY;
+        opaqueParameters[1] = BuiltinType.ANY;
+        when(mockExpr.getOpaqueParameters()).thenReturn(opaqueParameters);
+
+        // Tests the return type. It should be either ANY or NULLABLE/MISSABLE.
+        IResultTypeComputer instance = (IResultTypeComputer) c.getField("INSTANCE").get(null);
+        IAType resultType = instance.computeType(mockExpr, mockTypeEnv, mockMetadataProvider);
+        ATypeTag typeTag = resultType.getTypeTag();
+        if (typeTag == ATypeTag.ANY) {
+            return true;
+        }
+        if (typeTag == ATypeTag.UNION) {
+            AUnionType unionType = (AUnionType) resultType;
+            return unionType.isMissableType() && unionType.isNullableType();
+        }
+        return false;
+    }
+}