http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/StringBooleanTypeComputer.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/StringBooleanTypeComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/StringBooleanTypeComputer.java
new file mode 100644
index 0000000..10b6888
--- /dev/null
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/StringBooleanTypeComputer.java
@@ -0,0 +1,34 @@
+/*
+ * 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.types.BuiltinType;
+import org.apache.asterix.om.types.IAType;
+
+public class StringBooleanTypeComputer extends AbstractStringTypeComputer {
+    public static final StringBooleanTypeComputer INSTANCE = new 
StringBooleanTypeComputer();
+
+    private StringBooleanTypeComputer() {
+    }
+
+    @Override
+    public IAType getResultType(IAType... types) {
+        return BuiltinType.ABOOLEAN;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/StringStringTypeComputer.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/StringStringTypeComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/StringStringTypeComputer.java
new file mode 100644
index 0000000..bce0cef
--- /dev/null
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/StringStringTypeComputer.java
@@ -0,0 +1,35 @@
+/*
+ * 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.types.BuiltinType;
+import org.apache.asterix.om.types.IAType;
+
+public class StringStringTypeComputer extends AbstractStringTypeComputer {
+    public static final StringStringTypeComputer INSTANCE = new 
StringStringTypeComputer();
+
+    private StringStringTypeComputer() {
+    }
+
+    @Override
+    public IAType getResultType(IAType... inputTypes) {
+        return BuiltinType.ASTRING;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/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 4ceec49..40c57a4 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
@@ -54,10 +54,10 @@ public class SubsetCollectionTypeComputer implements 
IResultTypeComputer {
             }
             case UNION: {
                 AUnionType ut = (AUnionType) t;
-                if (!ut.isNullableType()) {
+                if (!ut.isUnknownableType()) {
                     throw new AlgebricksException("Expecting collection type. 
Found " + t);
                 }
-                IAType t2 = ut.getUnionList().get(1);
+                IAType t2 = ut.getActualType();
                 ATypeTag tag2 = t2.getTypeTag();
                 if (tag2 == ATypeTag.UNORDEREDLIST || tag2 == 
ATypeTag.ORDEREDLIST) {
                     AbstractCollectionType act = (AbstractCollectionType) t2;

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/Substring2TypeComputer.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/Substring2TypeComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/Substring2TypeComputer.java
index 6cc2f6d..f1000b9 100644
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/Substring2TypeComputer.java
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/Substring2TypeComputer.java
@@ -18,65 +18,36 @@
  */
 package org.apache.asterix.om.typecomputer.impl;
 
-import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
+import org.apache.asterix.om.typecomputer.base.AbstractResultTypeComputer;
 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.asterix.om.util.NonTaggedFormatUtil;
 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;
 
-public class Substring2TypeComputer implements IResultTypeComputer {
+public class Substring2TypeComputer extends AbstractResultTypeComputer {
     public static final Substring2TypeComputer INSTANCE = new 
Substring2TypeComputer();
 
     @Override
-    public IAType computeType(ILogicalExpression expression, 
IVariableTypeEnvironment env,
-            IMetadataProvider<?, ?> metadataProvider) throws 
AlgebricksException {
-        AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) 
expression;
-        if (fce.getArguments().size() < 2) {
-            throw new AlgebricksException("Wrong Argument Number.");
+    public void checkArgType(int argIndex, IAType type) throws 
AlgebricksException {
+        ATypeTag tag = type.getTypeTag();
+        if (argIndex == 0 && tag != ATypeTag.STRING) {
+            throw new AlgebricksException("First argument should be string 
Type.");
         }
-        ILogicalExpression arg0 = fce.getArguments().get(0).getValue();
-        ILogicalExpression arg1 = fce.getArguments().get(1).getValue();
-        IAType t0, t1;
-        try {
-            t0 = (IAType) env.getType(arg0);
-            t1 = (IAType) env.getType(arg1);
-        } catch (AlgebricksException e) {
-            throw new AlgebricksException(e);
-        }
-
-        ATypeTag tag0, tag1;
-        if (NonTaggedFormatUtil.isOptional(t0)) {
-            tag0 = ((AUnionType) t0).getNullableType().getTypeTag();
-        } else {
-            tag0 = t0.getTypeTag();
-        }
-
-        if (NonTaggedFormatUtil.isOptional(t1)) {
-            tag1 = ((AUnionType) t1).getNullableType().getTypeTag();
-        } else {
-            tag1 = t1.getTypeTag();
-        }
-
-        // Allow substring to work with ANY types, i.e., types that are 
unknown at compile time.
-        if (tag0 == ATypeTag.ANY || tag1 == ATypeTag.ANY) {
-            return BuiltinType.ANY;
-        }
-
-        if (tag0 != ATypeTag.NULL && tag0 != ATypeTag.STRING) {
-            throw new AlgebricksException("First argument should be String 
Type.");
-        }
-
-        if (tag1 != ATypeTag.NULL && tag1 != ATypeTag.INT8 && tag1 != 
ATypeTag.INT16 && tag1 != ATypeTag.INT32
-                && tag1 != ATypeTag.INT64) {
-            throw new AlgebricksException("Second argument should be integer 
Type.");
+        if (argIndex == 1) {
+            switch (tag) {
+                case INT8:
+                case INT16:
+                case INT32:
+                case INT64:
+                    break;
+                default:
+                    throw new AlgebricksException("Second argument should be 
integer Type.");
+            }
         }
+    }
 
+    @Override
+    public IAType getResultType(IAType... types) {
         return BuiltinType.ASTRING;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubstringTypeComputer.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubstringTypeComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubstringTypeComputer.java
index b6c5394..537056a 100644
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubstringTypeComputer.java
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubstringTypeComputer.java
@@ -18,72 +18,36 @@
  */
 package org.apache.asterix.om.typecomputer.impl;
 
-import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
+import org.apache.asterix.om.typecomputer.base.AbstractResultTypeComputer;
 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.asterix.om.util.NonTaggedFormatUtil;
 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;
 
-public class SubstringTypeComputer implements IResultTypeComputer {
+public class SubstringTypeComputer extends AbstractResultTypeComputer {
     public static final SubstringTypeComputer INSTANCE = new 
SubstringTypeComputer();
 
     @Override
-    public IAType computeType(ILogicalExpression expression, 
IVariableTypeEnvironment env,
-            IMetadataProvider<?, ?> metadataProvider) throws 
AlgebricksException {
-        AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) 
expression;
-        if (fce.getArguments().size() < 3)
-            throw new AlgebricksException("Wrong Argument Number.");
-        ILogicalExpression arg0 = fce.getArguments().get(0).getValue();
-        ILogicalExpression arg1 = fce.getArguments().get(1).getValue();
-        ILogicalExpression arg2 = fce.getArguments().get(2).getValue();
-        IAType t0, t1, t2;
-        try {
-            t0 = (IAType) env.getType(arg0);
-            t1 = (IAType) env.getType(arg1);
-            t2 = (IAType) env.getType(arg2);
-        } catch (AlgebricksException e) {
-            throw new AlgebricksException(e);
+    public void checkArgType(int argIndex, IAType type) throws 
AlgebricksException {
+        ATypeTag tag = type.getTypeTag();
+        if (argIndex == 0 && tag != ATypeTag.STRING) {
+            throw new AlgebricksException("First argument should be string 
Type.");
         }
-
-        ATypeTag tag0, tag1, tag2;
-        if (NonTaggedFormatUtil.isOptional(t0))
-            tag0 = ((AUnionType) t0).getNullableType().getTypeTag();
-        else
-            tag0 = t0.getTypeTag();
-
-        if (NonTaggedFormatUtil.isOptional(t1))
-            tag1 = ((AUnionType) t1).getNullableType().getTypeTag();
-        else
-            tag1 = t1.getTypeTag();
-
-        if (NonTaggedFormatUtil.isOptional(t2))
-            tag2 = ((AUnionType) t2).getNullableType().getTypeTag();
-        else
-            tag2 = t2.getTypeTag();
-
-        if (tag0 == ATypeTag.ANY || tag1 == ATypeTag.ANY || tag2 == 
ATypeTag.ANY)
-            return BuiltinType.ANY;
-
-        if (tag0 != ATypeTag.NULL && tag0 != ATypeTag.STRING) {
-            throw new AlgebricksException("First argument should be String 
Type.");
-        }
-
-        if (tag1 != ATypeTag.NULL && tag1 != ATypeTag.INT8 && tag1 != 
ATypeTag.INT16 && tag1 != ATypeTag.INT32
-                && tag1 != ATypeTag.INT64) {
-            throw new AlgebricksException("Second argument should be integer 
Type.");
-        }
-
-        if (tag2 != ATypeTag.NULL && tag2 != ATypeTag.INT8 && tag2 != 
ATypeTag.INT16 && tag2 != ATypeTag.INT32
-                && tag2 != ATypeTag.INT64) {
-            throw new AlgebricksException("Third argument should be integer 
Type.");
+        if (argIndex > 0 && argIndex <= 2) {
+            switch (tag) {
+                case INT8:
+                case INT16:
+                case INT32:
+                case INT64:
+                    break;
+                default:
+                    throw new AlgebricksException("Second argument should be 
integer Type.");
+            }
         }
+    }
 
+    @Override
+    public IAType getResultType(IAType... types) {
         return BuiltinType.ASTRING;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SwitchCaseComputer.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SwitchCaseComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SwitchCaseComputer.java
new file mode 100644
index 0000000..167cb44
--- /dev/null
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SwitchCaseComputer.java
@@ -0,0 +1,66 @@
+/*
+ * 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.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;
+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;
+
+public class SwitchCaseComputer implements IResultTypeComputer {
+
+    private static final String ERR_MSG = "switch case should have at least 3 
parameters";
+
+    public static final IResultTypeComputer INSTANCE = new 
SwitchCaseComputer();
+
+    private SwitchCaseComputer() {
+    }
+
+    @Override
+    public IAType computeType(ILogicalExpression expression, 
IVariableTypeEnvironment env,
+            IMetadataProvider<?, ?> metadataProvider) throws 
AlgebricksException {
+        AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) 
expression;
+        if (fce.getArguments().size() < 3) {
+            throw new AlgebricksException(ERR_MSG);
+        }
+
+        IAType currentType = null;
+        boolean any = false;
+        boolean missable = false;
+        for (int i = 2; i < fce.getArguments().size(); i += 2) {
+            IAType type = (IAType) 
env.getType(fce.getArguments().get(i).getValue());
+            if (type.getTypeTag() == ATypeTag.UNION) {
+                type = ((AUnionType) type).getActualType();
+                missable = true;
+            }
+            if (currentType != null && !type.equals(currentType)) {
+                any = true;
+                break;
+            }
+            currentType = type;
+        }
+        return any ? BuiltinType.ANY : missable ? 
AUnionType.createMissableType(currentType) : currentType;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TripleStringBoolOrNullTypeComputer.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TripleStringBoolOrNullTypeComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TripleStringBoolOrNullTypeComputer.java
deleted file mode 100644
index 36c5d71..0000000
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TripleStringBoolOrNullTypeComputer.java
+++ /dev/null
@@ -1,43 +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.types.AUnionType;
-import org.apache.asterix.om.types.BuiltinType;
-import org.apache.asterix.om.types.IAType;
-import org.apache.asterix.om.types.TypeHelper;
-
-/**
- * @author Xiaoyu Ma
- */
-public class TripleStringBoolOrNullTypeComputer extends 
AbstractTripleStringTypeComputer {
-    public static final TripleStringBoolOrNullTypeComputer INSTANCE = new 
TripleStringBoolOrNullTypeComputer();
-
-    private TripleStringBoolOrNullTypeComputer() {
-    }
-
-    @Override
-    public IAType getResultType(IAType t0, IAType t1, IAType t2) {
-        if (TypeHelper.canBeNull(t0) || TypeHelper.canBeNull(t1) || 
TypeHelper.canBeNull(t2)) {
-            return AUnionType.createNullableType(BuiltinType.ABOOLEAN);
-        }
-        return BuiltinType.ABOOLEAN;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TripleStringStringOrNullTypeComputer.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TripleStringStringOrNullTypeComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TripleStringStringOrNullTypeComputer.java
deleted file mode 100644
index b00d474..0000000
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TripleStringStringOrNullTypeComputer.java
+++ /dev/null
@@ -1,42 +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.types.AUnionType;
-import org.apache.asterix.om.types.BuiltinType;
-import org.apache.asterix.om.types.IAType;
-import org.apache.asterix.om.types.TypeHelper;
-
-/**
- * @author Xiaoyu Ma
- */
-public class TripleStringStringOrNullTypeComputer extends 
AbstractTripleStringTypeComputer {
-    public static final TripleStringStringOrNullTypeComputer INSTANCE = new 
TripleStringStringOrNullTypeComputer();
-
-    private TripleStringStringOrNullTypeComputer() {
-    }
-
-    @Override
-    public IAType getResultType(IAType t0, IAType t1, IAType t2) {
-        if (TypeHelper.canBeNull(t0) || TypeHelper.canBeNull(t1) || 
TypeHelper.canBeNull(t2)) {
-            return AUnionType.createNullableType(BuiltinType.ASTRING);
-        }
-        return BuiltinType.ASTRING;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeCompatibilityChecker.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeCompatibilityChecker.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeCompatibilityChecker.java
deleted file mode 100644
index 565ed02..0000000
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeCompatibilityChecker.java
+++ /dev/null
@@ -1,81 +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.types.ATypeTag;
-import org.apache.asterix.om.types.AUnionType;
-import org.apache.asterix.om.types.BuiltinType;
-import org.apache.asterix.om.types.IAType;
-
-class TypeCompatibilityChecker {
-    private final List<IAType> possibleTypes;
-    private boolean nullEncountered;
-
-    public TypeCompatibilityChecker() {
-        possibleTypes = new ArrayList<IAType>();
-        nullEncountered = false;
-    }
-
-    public void reset() {
-        possibleTypes.clear();
-        nullEncountered = false;
-    }
-
-    public void addPossibleType(IAType type) {
-        if (type.getTypeTag() == ATypeTag.UNION) {
-            List<IAType> typeList = ((AUnionType) type).getUnionList();
-            for (IAType t : typeList) {
-                if (t.getTypeTag() != ATypeTag.NULL) {
-                    //CONCAT_NON_NULL cannot return null because it's only 
used for if-else construct
-                    if (!possibleTypes.contains(t)) {
-                        possibleTypes.add(t);
-                    }
-                } else {
-                    nullEncountered = true;
-                }
-            }
-        } else {
-            if (type.getTypeTag() != ATypeTag.NULL) {
-                if (!possibleTypes.contains(type)) {
-                    possibleTypes.add(type);
-                }
-            } else {
-                nullEncountered = true;
-            }
-        }
-    }
-
-    public IAType getCompatibleType() {
-        switch (possibleTypes.size()) {
-            case 0:
-                return BuiltinType.ANULL;
-            case 1:
-                if (nullEncountered) {
-                    return AUnionType.createNullableType(possibleTypes.get(0));
-                } else {
-                    return possibleTypes.get(0);
-                }
-        }
-        return BuiltinType.ANY;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/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
new file mode 100644
index 0000000..f8cc9e6
--- /dev/null
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputeUtils.java
@@ -0,0 +1,222 @@
+/*
+ * 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.types.AOrderedListType;
+import org.apache.asterix.om.types.ARecordType;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AUnionType;
+import org.apache.asterix.om.types.AUnorderedListType;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.commons.lang3.mutable.Mutable;
+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;
+
+public class TypeComputeUtils {
+
+    private static final byte CERTAIN = 1;
+    private static final byte NULLABLE = 2;
+    private static final byte MISSABLE = 4;
+    private static final byte MISSING = 8;
+    private static final byte NULL = 16;
+
+    @FunctionalInterface
+    public static interface ArgTypeChecker {
+        public void checkArgTypes(int argIndex, IAType argType) throws 
AlgebricksException;
+    }
+
+    @FunctionalInterface
+    public static interface ResultTypeGenerator {
+        public IAType getResultType(IAType... knownInputTypes);
+    }
+
+    private TypeComputeUtils() {
+    }
+
+    /**
+     * Resolve the result type of an expression.
+     *
+     * @param expr,
+     *            the expression to consider.
+     * @param env,
+     *            the type environment.
+     * @param checker,
+     *            the argument type checker.
+     * @param resultTypeGenerator,
+     *            the result type generator.
+     * @param propagateNullAndMissing,
+     *            whether the expression follows 
MISSING/NULL-in-MISSING/NULL-out semantics.
+     * @return the resolved result type with considering optional types.
+     * @throws AlgebricksException
+     */
+    public static IAType resolveResultType(ILogicalExpression expr, 
IVariableTypeEnvironment env,
+            ArgTypeChecker checker, ResultTypeGenerator resultTypeGenerator, 
boolean propagateNullAndMissing)
+            throws AlgebricksException {
+        AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) 
expr;
+
+        IAType[] inputTypes = new IAType[fce.getArguments().size()];
+        int index = 0;
+        for (Mutable<ILogicalExpression> argRef : fce.getArguments()) {
+            ILogicalExpression arg = argRef.getValue();
+            inputTypes[index++] = (IAType) env.getType(arg);
+        }
+
+        // Checks input types and computes result types.
+        IAType[] knownInputTypes = TypeComputeUtils.getActualType(inputTypes);
+        boolean[] unknownable = TypeComputeUtils.isUnknownableType(inputTypes);
+        for (int argIndex = 0; argIndex < knownInputTypes.length; ++argIndex) {
+            ATypeTag argTypeTag = knownInputTypes[argIndex].getTypeTag();
+            if (unknownable[argIndex] || argTypeTag == ATypeTag.ANY || 
argTypeTag == ATypeTag.NULL
+                    || argTypeTag == ATypeTag.MISSING) {
+                continue;
+            }
+            checker.checkArgTypes(argIndex, knownInputTypes[argIndex]);
+        }
+
+        // Computes the result type.
+        byte category = TypeComputeUtils.resolveCateogry(inputTypes);
+        if (propagateNullAndMissing) {
+            if (category == MISSING) {
+                return BuiltinType.AMISSING;
+            }
+            if (category == NULL) {
+                return BuiltinType.ANULL;
+            }
+            return 
TypeComputeUtils.getResultType(resultTypeGenerator.getResultType(knownInputTypes),
 category);
+        } else {
+            return resultTypeGenerator.getResultType(knownInputTypes);
+        }
+    }
+
+    private static byte resolveCateogry(IAType... inputTypes) {
+        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()) {
+                    category |= NULLABLE;
+                }
+                if (unionType.isMissableType()) {
+                    category |= MISSABLE;
+                }
+            } else if (inputTypeTag == ATypeTag.MISSING) {
+                return MISSING;
+            } else if (inputTypeTag == ATypeTag.NULL) {
+                meetNull = true;
+            }
+        }
+        if (meetNull) {
+            return NULL;
+        }
+        return category;
+    }
+
+    private static IAType getResultType(IAType type, byte category) {
+        if (category == CERTAIN) {
+            return type;
+        }
+        IAType resultType = type;
+        if ((category & NULLABLE) != 0 || (category & NULL) != 0) {
+            resultType = AUnionType.createNullableType(resultType);
+        }
+        if ((category & MISSABLE) != 0 || (category & MISSING) != 0) {
+            resultType = AUnionType.createMissableType(resultType);
+        }
+        return resultType;
+    }
+
+    private static IAType[] getActualType(IAType... inputTypes) {
+        IAType[] actualTypes = new IAType[inputTypes.length];
+        int index = 0;
+        for (IAType inputType : inputTypes) {
+            actualTypes[index++] = getActualType(inputType);
+        }
+        return actualTypes;
+    }
+
+    private static boolean[] isUnknownableType(IAType... inputTypes) {
+        boolean[] unknownable = new boolean[inputTypes.length];
+        for (int index = 0; index < unknownable.length; ++index) {
+            IAType type = inputTypes[index];
+            unknownable[index] = false;
+            if (type.getTypeTag() != ATypeTag.UNION) {
+                continue;
+            } else {
+                AUnionType unionType = (AUnionType) type;
+                unknownable[index] = unionType.isUnknownableType();
+            }
+        }
+        return unknownable;
+    }
+
+    public static IAType getActualType(IAType inputType) {
+        return inputType.getTypeTag() == ATypeTag.UNION ? ((AUnionType) 
inputType).getActualType() : inputType;
+    }
+
+    public static ARecordType extractRecordType(IAType t) {
+        switch (t.getTypeTag()) {
+            case RECORD:
+                return (ARecordType) t;
+            case UNION:
+                IAType innerType = ((AUnionType) t).getActualType();
+                if (innerType.getTypeTag() == ATypeTag.RECORD) {
+                    return (ARecordType) innerType;
+                } else {
+                    return null;
+                }
+            default:
+                return null;
+        }
+    }
+
+    public static AOrderedListType extractOrderedListType(IAType t) {
+        if (t.getTypeTag() == ATypeTag.ORDEREDLIST) {
+            return (AOrderedListType) t;
+        }
+
+        if (t.getTypeTag() == ATypeTag.UNION) {
+            IAType innerType = ((AUnionType) t).getActualType();
+            if (innerType.getTypeTag() == ATypeTag.ORDEREDLIST) {
+                return (AOrderedListType) innerType;
+            }
+        }
+        return null;
+    }
+
+    public static AUnorderedListType extractUnorderedListType(IAType t) {
+        if (t.getTypeTag() == ATypeTag.UNORDEREDLIST) {
+            return (AUnorderedListType) t;
+        }
+        if (t.getTypeTag() == ATypeTag.UNION) {
+            AUnionType unionType = (AUnionType) t;
+            IAType innerType = unionType.getActualType();
+            if (innerType.getTypeTag() == ATypeTag.UNORDEREDLIST) {
+                return (AUnorderedListType) innerType;
+            }
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputerUtils.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputerUtils.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputerUtils.java
deleted file mode 100644
index cba988b..0000000
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/TypeComputerUtils.java
+++ /dev/null
@@ -1,75 +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.types.AOrderedListType;
-import org.apache.asterix.om.types.ARecordType;
-import org.apache.asterix.om.types.ATypeTag;
-import org.apache.asterix.om.types.AUnionType;
-import org.apache.asterix.om.types.AUnorderedListType;
-import org.apache.asterix.om.types.IAType;
-
-public class TypeComputerUtils {
-
-    public static ARecordType extractRecordType(IAType t) {
-        if (t.getTypeTag() == ATypeTag.RECORD) {
-            return (ARecordType) t;
-        }
-
-        if (t.getTypeTag() == ATypeTag.UNION) {
-            IAType innerType = ((AUnionType) t).getUnionList().get(1);
-            if (innerType.getTypeTag() == ATypeTag.RECORD) {
-                return (ARecordType) innerType;
-            }
-        }
-
-        return null;
-    }
-
-    public static AOrderedListType extractOrderedListType(IAType t) {
-        if (t.getTypeTag() == ATypeTag.ORDEREDLIST) {
-            return (AOrderedListType) t;
-        }
-
-        if (t.getTypeTag() == ATypeTag.UNION) {
-            IAType innerType = ((AUnionType) t).getUnionList().get(1);
-            if (innerType.getTypeTag() == ATypeTag.ORDEREDLIST) {
-                return (AOrderedListType) innerType;
-            }
-        }
-
-        return null;
-    }
-
-    public static AUnorderedListType extractUnorderedListType(IAType t) {
-        if (t.getTypeTag() == ATypeTag.UNORDEREDLIST) {
-            return (AUnorderedListType) t;
-        }
-
-        if (t.getTypeTag() == ATypeTag.UNION) {
-            IAType innerType = ((AUnionType) t).getUnionList().get(1);
-            if (innerType.getTypeTag() == ATypeTag.UNORDEREDLIST) {
-                return (AUnorderedListType) innerType;
-            }
-        }
-
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryBinaryInt64OrNullTypeComputer.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryBinaryInt64OrNullTypeComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryBinaryInt64OrNullTypeComputer.java
deleted file mode 100644
index ab94c4f..0000000
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryBinaryInt64OrNullTypeComputer.java
+++ /dev/null
@@ -1,67 +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.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.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.common.exceptions.NotImplementedException;
-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;
-
-public class UnaryBinaryInt64OrNullTypeComputer implements IResultTypeComputer 
{
-    public static final UnaryBinaryInt64OrNullTypeComputer INSTANCE = new 
UnaryBinaryInt64OrNullTypeComputer();
-
-    private UnaryBinaryInt64OrNullTypeComputer() {
-
-    }
-
-    @Override
-    public IAType computeType(ILogicalExpression expression, 
IVariableTypeEnvironment env,
-            IMetadataProvider<?, ?> metadataProvider) throws 
AlgebricksException {
-        AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) 
expression;
-        if (fce.getArguments().size() != 1) {
-            throw new AlgebricksException("Wrong Argument Number.");
-        }
-        ILogicalExpression arg0 = fce.getArguments().get(0).getValue();
-        IAType t0;
-        t0 = (IAType) env.getType(arg0);
-        if (t0.getTypeTag() != ATypeTag.NULL
-                && t0.getTypeTag() != ATypeTag.BINARY
-                && (t0.getTypeTag() == ATypeTag.UNION && !((AUnionType) 
t0).getUnionList()
-                        .contains(BuiltinType.ABINARY))) {
-            throw new NotImplementedException("Expects Binary Type.");
-        }
-
-        if (t0.getTypeTag() == ATypeTag.NULL) {
-            return BuiltinType.ANULL;
-        }
-
-        if (t0.getTypeTag() == ATypeTag.BINARY || 
t0.getTypeTag().equals(ATypeTag.UNION)) {
-            return AUnionType.createNullableType(BuiltinType.AINT64, 
"binary-length-Result");
-        }
-        throw new AlgebricksException("Cannot compute type");
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryBinaryInt64TypeComputer.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryBinaryInt64TypeComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryBinaryInt64TypeComputer.java
new file mode 100644
index 0000000..0105fe3
--- /dev/null
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryBinaryInt64TypeComputer.java
@@ -0,0 +1,50 @@
+/*
+ * 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.AbstractResultTypeComputer;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+
+public class UnaryBinaryInt64TypeComputer extends AbstractResultTypeComputer {
+    public static final UnaryBinaryInt64TypeComputer INSTANCE = new 
UnaryBinaryInt64TypeComputer();
+
+    private UnaryBinaryInt64TypeComputer() {
+    }
+
+    @Override
+    public void checkArgType(int argIndex, IAType type) throws 
AlgebricksException {
+        ATypeTag tag = type.getTypeTag();
+        if (argIndex == 0) {
+            if (tag != ATypeTag.BINARY) {
+                throw new AlgebricksException("The argument should be binary 
Type.");
+            }
+        } else {
+            throw new AlgebricksException("Wrong Argument Number.");
+        }
+    }
+
+    @Override
+    public IAType getResultType(IAType... types) {
+        return BuiltinType.AINT64;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryBooleanOrNullFunctionTypeComputer.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryBooleanOrNullFunctionTypeComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryBooleanOrNullFunctionTypeComputer.java
deleted file mode 100644
index 6c0b53c..0000000
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryBooleanOrNullFunctionTypeComputer.java
+++ /dev/null
@@ -1,60 +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.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.asterix.om.types.TypeHelper;
-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;
-
-public class UnaryBooleanOrNullFunctionTypeComputer implements 
IResultTypeComputer {
-
-    public static final UnaryBooleanOrNullFunctionTypeComputer INSTANCE = new 
UnaryBooleanOrNullFunctionTypeComputer();
-
-    private UnaryBooleanOrNullFunctionTypeComputer() {
-    }
-
-    @Override
-    public IAType computeType(ILogicalExpression expression, 
IVariableTypeEnvironment env,
-            IMetadataProvider<?, ?> metadataProvider) throws 
AlgebricksException {
-        AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) 
expression;
-        ILogicalExpression arg0 = fce.getArguments().get(0).getValue();
-        IAType t0;
-        try {
-            t0 = (IAType) env.getType(arg0);
-        } catch (AlgebricksException e) {
-            throw new AlgebricksException(e);
-        }
-        if (t0.getTypeTag() == ATypeTag.NULL) {
-            return BuiltinType.ANULL;
-        }
-        if (TypeHelper.canBeNull(t0)) {
-            return AUnionType.createNullableType(BuiltinType.ABOOLEAN, 
"OptionalBoolean");
-        }
-        return BuiltinType.ABOOLEAN;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryMinusTypeComputer.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryMinusTypeComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryMinusTypeComputer.java
new file mode 100644
index 0000000..31e559e
--- /dev/null
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryMinusTypeComputer.java
@@ -0,0 +1,66 @@
+/*
+ * 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.AbstractResultTypeComputer;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.common.exceptions.NotImplementedException;
+
+public class UnaryMinusTypeComputer extends AbstractResultTypeComputer {
+
+    public static final UnaryMinusTypeComputer INSTANCE = new 
UnaryMinusTypeComputer();
+
+    private UnaryMinusTypeComputer() {
+    }
+
+    @Override
+    public void checkArgType(int argIndex, IAType type) throws 
AlgebricksException {
+        ATypeTag tag = type.getTypeTag();
+        switch (tag) {
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case FLOAT:
+            case DOUBLE:
+                break;
+            default:
+                throw new NotImplementedException(
+                        "Negative operations are not implemented for " + 
type.getDisplayName());
+        }
+    }
+
+    @Override
+    public IAType getResultType(IAType... knownTypes) {
+        ATypeTag tag = knownTypes[0].getTypeTag();
+        switch (tag) {
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case FLOAT:
+            case DOUBLE:
+                return knownTypes[0];
+            default:
+                return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryStringInt64OrNullTypeComputer.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryStringInt64OrNullTypeComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryStringInt64OrNullTypeComputer.java
deleted file mode 100644
index f41a719..0000000
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryStringInt64OrNullTypeComputer.java
+++ /dev/null
@@ -1,81 +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.BuiltinType;
-import org.apache.asterix.om.types.IAType;
-import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.common.exceptions.NotImplementedException;
-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;
-
-/**
- * @author Xiaoyu Ma
- */
-public class UnaryStringInt64OrNullTypeComputer implements IResultTypeComputer 
{
-
-    public static final UnaryStringInt64OrNullTypeComputer INSTANCE = new 
UnaryStringInt64OrNullTypeComputer();
-
-    private UnaryStringInt64OrNullTypeComputer() {
-    }
-
-    @Override
-    public IAType computeType(ILogicalExpression expression, 
IVariableTypeEnvironment env,
-            IMetadataProvider<?, ?> metadataProvider) throws 
AlgebricksException {
-        AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) 
expression;
-        if (fce.getArguments().isEmpty()) {
-            throw new AlgebricksException("Wrong Argument Number.");
-        }
-        ILogicalExpression arg0 = fce.getArguments().get(0).getValue();
-        IAType t0;
-        try {
-            t0 = (IAType) env.getType(arg0);
-        } catch (AlgebricksException e) {
-            throw new AlgebricksException(e);
-        }
-        if (t0.getTypeTag() == ATypeTag.ANY) {
-            return BuiltinType.ANY;
-        }
-
-        if (t0.getTypeTag() != ATypeTag.NULL && t0.getTypeTag() != 
ATypeTag.STRING && (t0.getTypeTag() == ATypeTag.UNION
-                && !((AUnionType) 
t0).getUnionList().contains(BuiltinType.ASTRING))) {
-            throw new NotImplementedException("Expects String Type.");
-        }
-
-        List<IAType> unionList = new ArrayList<IAType>();
-        unionList.add(BuiltinType.ANULL);
-        if (t0.getTypeTag() == ATypeTag.NULL) {
-            return BuiltinType.ANULL;
-        }
-
-        if (t0.getTypeTag() == ATypeTag.STRING || 
t0.getTypeTag().equals(ATypeTag.UNION)) {
-            return AUnionType.createNullableType(BuiltinType.AINT64, 
"String-length-Result");
-        }
-
-        throw new AlgebricksException("Cannot compute type");
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryStringInt64TypeComputer.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryStringInt64TypeComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryStringInt64TypeComputer.java
new file mode 100644
index 0000000..7208243
--- /dev/null
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryStringInt64TypeComputer.java
@@ -0,0 +1,50 @@
+/*
+ * 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.AbstractResultTypeComputer;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+
+public class UnaryStringInt64TypeComputer extends AbstractResultTypeComputer {
+
+    public static final UnaryStringInt64TypeComputer INSTANCE = new 
UnaryStringInt64TypeComputer();
+
+    private UnaryStringInt64TypeComputer() {
+    }
+
+    @Override
+    public void checkArgType(int argIndex, IAType type) throws 
AlgebricksException {
+        ATypeTag tag = type.getTypeTag();
+        if (argIndex == 0) {
+            if (tag != ATypeTag.STRING) {
+                throw new AlgebricksException("Second argument should be 
string Type.");
+            }
+        } else {
+            throw new AlgebricksException("Wrong Argument Number.");
+        }
+    }
+
+    @Override
+    public IAType getResultType(IAType... types) {
+        return BuiltinType.AINT64;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryStringOrNullTypeComputer.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryStringOrNullTypeComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryStringOrNullTypeComputer.java
deleted file mode 100644
index 4c11c8e..0000000
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnaryStringOrNullTypeComputer.java
+++ /dev/null
@@ -1,69 +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.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.asterix.om.types.TypeHelper;
-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;
-
-/**
- * @author Xiaoyu Ma
- */
-public class UnaryStringOrNullTypeComputer implements IResultTypeComputer {
-
-    public static final UnaryStringOrNullTypeComputer INSTANCE = new 
UnaryStringOrNullTypeComputer();
-
-    private UnaryStringOrNullTypeComputer() {
-    }
-
-    @Override
-    public IAType computeType(ILogicalExpression expression, 
IVariableTypeEnvironment env,
-            IMetadataProvider<?, ?> metadataProvider) throws 
AlgebricksException {
-        AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) 
expression;
-        if (fce.getArguments().isEmpty())
-            throw new AlgebricksException("Wrong Argument Number.");
-        ILogicalExpression arg0 = fce.getArguments().get(0).getValue();
-        IAType t0;
-        try {
-            t0 = (IAType) env.getType(arg0);
-        } catch (AlgebricksException e) {
-            throw new AlgebricksException(e);
-        }
-
-        if (TypeHelper.canBeNull(t0)) {
-            return AUnionType.createNullableType(BuiltinType.ASTRING);
-        }
-
-        if (t0.getTypeTag() == ATypeTag.NULL)
-            return BuiltinType.ANULL;
-
-        if (t0.getTypeTag() == ATypeTag.STRING)
-            return BuiltinType.ASTRING;
-
-        throw new AlgebricksException("Expects String Type.");
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnorderedListConstructorResultType.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnorderedListConstructorResultType.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnorderedListConstructorResultType.java
index 67b3c69..1e1d753 100644
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnorderedListConstructorResultType.java
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/UnorderedListConstructorResultType.java
@@ -19,15 +19,13 @@
 
 package org.apache.asterix.om.typecomputer.impl;
 
-import java.util.ArrayList;
-
 import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
-import org.apache.asterix.om.typecomputer.base.TypeComputerUtilities;
+import org.apache.asterix.om.typecomputer.base.TypeCastUtils;
+import org.apache.asterix.om.types.ATypeTag;
 import org.apache.asterix.om.types.AUnionType;
 import org.apache.asterix.om.types.AUnorderedListType;
 import org.apache.asterix.om.types.BuiltinType;
 import org.apache.asterix.om.types.IAType;
-import org.apache.asterix.om.util.NonTaggedFormatUtil;
 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;
@@ -46,24 +44,28 @@ public class UnorderedListConstructorResultType implements 
IResultTypeComputer {
         /**
          * if type has been top-down propagated, use the enforced type
          */
-        AUnorderedListType reqType = (AUnorderedListType) 
TypeComputerUtilities.getRequiredType(f);
-        if (reqType != null)
+        AUnorderedListType reqType = (AUnorderedListType) 
TypeCastUtils.getRequiredType(f);
+        if (reqType != null) {
             return reqType;
+        }
 
-        ArrayList<IAType> types = new ArrayList<IAType>();
+        IAType currentType = null;
+        boolean any = false;
         for (int k = 0; k < f.getArguments().size(); k++) {
             IAType type = (IAType) 
env.getType(f.getArguments().get(k).getValue());
-            if (NonTaggedFormatUtil.isOptional(type))
-                type = ((AUnionType) type).getNullableType();
-            if (types.indexOf(type) < 0) {
-                types.add(type);
+            if (type.getTypeTag() == ATypeTag.UNION) {
+                type = ((AUnionType) type).getActualType();
+            }
+            if (currentType != null && !currentType.equals(type)) {
+                any = true;
+                break;
             }
+            currentType = type;
         }
-        if (types.size() == 1) {
-            return new AUnorderedListType(types.get(0), null);
-        } else {
+        if (any || currentType == null) {
             return new AUnorderedListType(BuiltinType.ANY, null);
+        } else {
+            return new AUnorderedListType(currentType, null);
         }
-
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java
index 6147276..163421d 100644
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java
@@ -168,7 +168,7 @@ public class ARecordType extends AbstractComplexType {
             }
             if (subRecordType.getTypeTag().equals(ATypeTag.UNION)) {
                 //enforced SubType
-                subRecordType = ((AUnionType) subRecordType).getNullableType();
+                subRecordType = ((AUnionType) subRecordType).getActualType();
                 if (subRecordType.getTypeTag() != ATypeTag.RECORD) {
                     throw new AsterixException(
                             "Field accessor is not defined for values of type 
" + subRecordType.getTypeTag());

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ATypeTag.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ATypeTag.java 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ATypeTag.java
index 3dc2caa..4d6a96c 100644
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ATypeTag.java
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ATypeTag.java
@@ -40,7 +40,7 @@ public enum ATypeTag implements IEnumSerializer {
     FLOAT(11),
     DOUBLE(12),
     STRING(13),
-    NULL(14),
+    MISSING(14),
     BOOLEAN(15),
     DATETIME(16),
     DATE(17),
@@ -65,12 +65,14 @@ public enum ATypeTag implements IEnumSerializer {
     YEARMONTHDURATION(36),
     DAYTIMEDURATION(37),
     UUID(38),
-    SHORTWITHOUTTYPEINFO(40);
+    SHORTWITHOUTTYPEINFO(40),
+    NULL(41);
 
     /*
      * Serialized Tags begin
      */
     public static final byte SERIALIZED_STRING_TYPE_TAG = STRING.serialize();
+    public static final byte SERIALIZED_MISSING_TYPE_TAG = MISSING.serialize();
     public static final byte SERIALIZED_NULL_TYPE_TAG = NULL.serialize();
     public static final byte SERIALIZED_DOUBLE_TYPE_TAG = DOUBLE.serialize();
     public static final byte SERIALIZED_RECORD_TYPE_TAG = RECORD.serialize();

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AUnionType.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AUnionType.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AUnionType.java
index 65f0098..3c29e7f 100644
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AUnionType.java
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AUnionType.java
@@ -32,7 +32,7 @@ import org.json.JSONObject;
 public class AUnionType extends AbstractComplexType {
 
     private static final long serialVersionUID = 1L;
-    public static final int OPTIONAL_TYPE_INDEX_IN_UNION_LIST = 1;
+    private static final int OPTIONAL_TYPE_INDEX_IN_UNION_LIST = 0;
     private final List<IAType> unionList;
 
     public AUnionType(List<IAType> unionList, String typeName) {
@@ -44,18 +44,98 @@ public class AUnionType extends AbstractComplexType {
         return unionList;
     }
 
-    public void setTypeAtIndex(IAType type, int index) {
-        unionList.set(index, type);
+    public boolean isMissableType() {
+        return containsType(BuiltinType.AMISSING);
     }
 
     public boolean isNullableType() {
-        return unionList.size() == 2 && 
unionList.get(0).equals(BuiltinType.ANULL);
+        return containsType(BuiltinType.ANULL);
     }
 
-    public IAType getNullableType() {
+    public boolean isUnknownableType() {
+        return isMissableType() || isNullableType();
+    }
+
+    private boolean containsType(IAType t) {
+        for (int index = 0; index < unionList.size(); ++index) {
+            if (unionList.get(index) != null && 
unionList.get(index).equals(t)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public IAType getActualType() {
         return unionList.get(AUnionType.OPTIONAL_TYPE_INDEX_IN_UNION_LIST);
     }
 
+    public void setActualType(IAType type) {
+        if (AUnionType.OPTIONAL_TYPE_INDEX_IN_UNION_LIST < unionList.size()) {
+            unionList.set(AUnionType.OPTIONAL_TYPE_INDEX_IN_UNION_LIST, type);
+        } else {
+            unionList.add(type);
+        }
+    }
+
+    public static IAType createMissableType(IAType type, String typeName) {
+        if (type != null && type.getTypeTag() == ATypeTag.MISSING) {
+            return type;
+        }
+        List<IAType> unionList = new ArrayList<>();
+        if (type != null && type.getTypeTag() == ATypeTag.UNION) {
+            AUnionType unionType = (AUnionType) type;
+            unionList.addAll(unionType.getUnionList());
+        } else {
+            unionList.add(type);
+        }
+        unionList.add(BuiltinType.AMISSING);
+        return new AUnionType(unionList, typeName);
+    }
+
+    public static IAType createMissableType(IAType t) {
+        if (t != null && t.getTypeTag() == ATypeTag.MISSING) {
+            return t;
+        }
+        String s = t != null ? t.getTypeName() : null;
+        return createMissableType(t, s == null ? null : s + "?");
+    }
+
+    public static IAType createNullableType(IAType type, String typeName) {
+        if (type != null && type.getTypeTag() == ATypeTag.NULL) {
+            return type;
+        }
+        List<IAType> unionList = new ArrayList<>();
+        if (type != null && type.getTypeTag() == ATypeTag.UNION) {
+            AUnionType unionType = (AUnionType) type;
+            unionList.addAll(unionType.getUnionList());
+        } else {
+            unionList.add(type);
+        }
+        unionList.add(BuiltinType.ANULL);
+        return new AUnionType(unionList, typeName);
+    }
+
+    public static IAType createNullableType(IAType t) {
+        if (t != null && t.getTypeTag() == ATypeTag.NULL) {
+            return t;
+        }
+        String s = t != null ? t.getTypeName() : null;
+        return createNullableType(t, s == null ? null : s + "?");
+    }
+
+    public static IAType createUnknownableType(IAType type, String typeName) {
+        List<IAType> unionList = new ArrayList<>();
+        unionList.add(type);
+        unionList.add(BuiltinType.ANULL);
+        unionList.add(BuiltinType.AMISSING);
+        return new AUnionType(unionList, typeName);
+    }
+
+    public static IAType createUnknownableType(IAType t) {
+        String s = t != null ? t.getTypeName() : null;
+        return createUnknownableType(t, s == null ? null : s + "?");
+    }
+
     @Override
     public String getDisplayName() {
         return "AUnion";
@@ -92,22 +172,10 @@ public class AUnionType extends AbstractComplexType {
         return BuiltinType.ASTERIX_TYPE;
     }
 
-    public static AUnionType createNullableType(IAType type, String typeName) {
-        List<IAType> unionList = new ArrayList<IAType>();
-        unionList.add(BuiltinType.ANULL);
-        unionList.add(type);
-        return new AUnionType(unionList, typeName);
-    }
-
-    public static AUnionType createNullableType(IAType t) {
-        String s = t != null ? t.getTypeName() : null;
-        return createNullableType(t, s == null ? null : s + "?");
-    }
-
     @Override
     public void generateNestedDerivedTypeNames() {
-        if (isNullableType()) {
-            IAType nullableType = getNullableType();
+        if (isUnknownableType()) {
+            IAType nullableType = getActualType();
             if (nullableType.getTypeTag().isDerivedType() && 
nullableType.getTypeName() == null) {
                 AbstractComplexType derivedType = (AbstractComplexType) 
nullableType;
                 derivedType.setTypeName(getTypeName());

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/BuiltinType.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/BuiltinType.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/BuiltinType.java
index 620b9ae..f556de5 100644
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/BuiltinType.java
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/BuiltinType.java
@@ -286,6 +286,33 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
+    public final static BuiltinType AMISSING = new LowerCaseConstructorType() {
+
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String getDisplayName() {
+            return "Missing";
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return ATypeTag.MISSING;
+        }
+
+        @Override
+        public String getTypeName() {
+            return "missing";
+        }
+
+        @Override
+        public JSONObject toJSON() throws JSONException {
+            JSONObject type = new JSONObject();
+            type.put("type", "AMISSING");
+            return type;
+        }
+    };
+
     public final static BuiltinType ANULL = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeHelper.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeHelper.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeHelper.java
index 5c556d6..4839c41 100644
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeHelper.java
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeHelper.java
@@ -18,69 +18,44 @@
  */
 package org.apache.asterix.om.types;
 
-import java.util.ArrayList;
-import java.util.List;
-
 public class TypeHelper {
 
-    public static boolean canBeNull(IAType t) {
+    public static boolean canBeMissing(IAType t) {
         switch (t.getTypeTag()) {
-            case NULL: {
+            case MISSING:
                 return true;
-            }
-            case UNION: {
-                AUnionType ut = (AUnionType) t;
-                for (IAType t2 : ut.getUnionList()) {
-                    if (canBeNull(t2)) {
-                        return true;
-                    }
-                }
-                return false;
-            }
+            case UNION:
+                return ((AUnionType) t).isMissableType();
             default: {
                 return false;
             }
         }
     }
 
-    public static IAType getNonOptionalType(IAType t) {
-        if (t.getTypeTag() != ATypeTag.UNION) {
-            return t;
-        }
-        AUnionType ut = (AUnionType) t;
-        List<IAType> x = new ArrayList<IAType>();
-        for (IAType t1 : ut.getUnionList()) {
-            IAType y = getNonOptionalType(t1);
-            if (y != BuiltinType.ANULL) {
-                x.add(y);
-            }
-        }
-        if (x.isEmpty()) {
-            return BuiltinType.ANULL;
-        }
-        if (x.size() == 1) {
-            return x.get(0);
+    public static boolean canBeUnknown(IAType t) {
+        switch (t.getTypeTag()) {
+            case MISSING:
+            case NULL:
+                return true;
+            case UNION:
+                return ((AUnionType) t).isUnknownableType();
+            default:
+                return false;
         }
-        return new AUnionType(x, null);
     }
 
     public static boolean isClosed(IAType t) {
         switch (t.getTypeTag()) {
-            case ANY: {
+            case MISSING:
+            case ANY:
                 return false;
-            }
-            case UNION: {
-                AUnionType ut = (AUnionType) t;
-                for (IAType t1 : ut.getUnionList()) {
-                    if (!isClosed(t1)) {
-                        return false;
-                    }
+            case UNION:
+                if (!isClosed(((AUnionType) t).getActualType())) {
+                    return false;
                 }
                 return true;
-            }
-            default: {
+            default:
                 return true;
-            }
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeTagUtil.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeTagUtil.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeTagUtil.java
index a73ff73..2a50506 100644
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeTagUtil.java
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeTagUtil.java
@@ -42,6 +42,8 @@ public class TypeTagUtil {
                 return BuiltinType.ADOUBLE;
             case STRING:
                 return BuiltinType.ASTRING;
+            case MISSING:
+                return BuiltinType.AMISSING;
             case NULL:
                 return BuiltinType.ANULL;
             case BOOLEAN:

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/util/NonTaggedFormatUtil.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/util/NonTaggedFormatUtil.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/util/NonTaggedFormatUtil.java
index c24ce45..1009fbb 100644
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/util/NonTaggedFormatUtil.java
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/util/NonTaggedFormatUtil.java
@@ -18,8 +18,6 @@
  */
 package org.apache.asterix.om.util;
 
-import java.util.List;
-
 import org.apache.asterix.common.config.DatasetConfig.IndexType;
 import org.apache.asterix.common.exceptions.AsterixException;
 import 
org.apache.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
@@ -50,10 +48,11 @@ public final class NonTaggedFormatUtil {
     public static final boolean isFixedSizedCollection(IAType type) {
         switch (type.getTypeTag()) {
             case UNION:
-                if (!((AUnionType) type).isNullableType())
+                if (!((AUnionType) type).isUnknownableType()) {
                     return false;
-                else
-                    return isFixedSizedCollection(((AUnionType) 
type).getNullableType());
+                } else {
+                    return isFixedSizedCollection(((AUnionType) 
type).getActualType());
+                }
             default:
                 return isFixedSizedCollection(type.getTypeTag());
         }
@@ -76,19 +75,20 @@ public final class NonTaggedFormatUtil {
     }
 
     public static final boolean hasNullableField(ARecordType recType) {
-        IAType type;
-        List<IAType> unionList;
         for (int i = 0; i < recType.getFieldTypes().length; i++) {
-            type = recType.getFieldTypes()[i];
+            IAType type = recType.getFieldTypes()[i];
             if (type != null) {
-                if (type.getTypeTag() == ATypeTag.NULL)
+                ATypeTag tag = type.getTypeTag();
+                if (tag == ATypeTag.NULL) {
+                    return true;
+                }
+                if (tag != ATypeTag.UNION) {
+                    continue;
+                }
+                // union
+                AUnionType unionType = (AUnionType) type;
+                if (unionType.isUnknownableType()) {
                     return true;
-                if (type.getTypeTag() == ATypeTag.UNION) { // union
-                    unionList = ((AUnionType) type).getUnionList();
-                    for (int j = 0; j < unionList.size(); j++)
-                        if (unionList.get(j).getTypeTag() == ATypeTag.NULL)
-                            return true;
-
                 }
             }
         }
@@ -102,7 +102,7 @@ public final class NonTaggedFormatUtil {
      * @return true if it is optional; false otherwise
      */
     public static boolean isOptional(IAType type) {
-        return type.getTypeTag() == ATypeTag.UNION && ((AUnionType) 
type).isNullableType();
+        return type.getTypeTag() == ATypeTag.UNION && ((AUnionType) 
type).isUnknownableType();
     }
 
     public static int getFieldValueLength(byte[] serNonTaggedAObject, int 
offset, ATypeTag typeTag, boolean tagged)
@@ -114,6 +114,7 @@ public final class NonTaggedFormatUtil {
                     throw new AsterixException("Field value has type tag ANY, 
but it should have a concrete type.");
                 }
                 return getFieldValueLength(serNonTaggedAObject, offset, tag, 
true) + 1;
+            case MISSING:
             case NULL:
                 return 0;
             case BOOLEAN:
@@ -139,10 +140,11 @@ public final class NonTaggedFormatUtil {
             case UUID:
                 return 16;
             case INTERVAL:
-                if (tagged)
+                if (tagged) {
                     return 
AIntervalSerializerDeserializer.getIntervalLength(serNonTaggedAObject, offset + 
1);
-                else
+                } else {
                     return 
AIntervalSerializerDeserializer.getIntervalLength(serNonTaggedAObject, offset);
+                }
             case POINT3D:
             case CIRCLE:
                 return 24;
@@ -150,10 +152,11 @@ public final class NonTaggedFormatUtil {
             case RECTANGLE:
                 return 32;
             case POLYGON:
-                if (tagged)
+                if (tagged) {
                     return 
AInt16SerializerDeserializer.getShort(serNonTaggedAObject, offset + 1) * 16 + 2;
-                else
+                } else {
                     return 
AInt16SerializerDeserializer.getShort(serNonTaggedAObject, offset) * 16 + 2;
+                }
             case STRING:
                 if (tagged) {
                     int len = UTF8StringUtil.getUTFLength(serNonTaggedAObject, 
offset + 1);
@@ -171,21 +174,24 @@ public final class NonTaggedFormatUtil {
                     return len + 
ByteArrayPointable.getNumberBytesToStoreMeta(len);
                 }
             case RECORD:
-                if (tagged)
+                if (tagged) {
                     return 
ARecordSerializerDeserializer.getRecordLength(serNonTaggedAObject, offset + 1) 
- 1;
-                else
+                } else {
                     return 
ARecordSerializerDeserializer.getRecordLength(serNonTaggedAObject, offset) - 1;
+                }
             case ORDEREDLIST:
-                if (tagged)
+                if (tagged) {
                     return 
AOrderedListSerializerDeserializer.getOrderedListLength(serNonTaggedAObject, 
offset + 1) - 1;
-                else
+                } else {
                     return 
AOrderedListSerializerDeserializer.getOrderedListLength(serNonTaggedAObject, 
offset) - 1;
+                }
             case UNORDEREDLIST:
-                if (tagged)
+                if (tagged) {
                     return 
AUnorderedListSerializerDeserializer.getUnorderedListLength(serNonTaggedAObject,
 offset + 1)
                             - 1;
-                else
+                } else {
                     return 
AUnorderedListSerializerDeserializer.getUnorderedListLength(serNonTaggedAObject,
 offset) - 1;
+                }
             default:
                 throw new NotImplementedException(
                         "No getLength implemented for a value of this type " + 
typeTag + " .");

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/visitors/IOMVisitor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/visitors/IOMVisitor.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/visitors/IOMVisitor.java
index 2bc80af..6ef6a9d 100644
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/visitors/IOMVisitor.java
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/visitors/IOMVisitor.java
@@ -35,6 +35,7 @@ import org.apache.asterix.om.base.AInt64;
 import org.apache.asterix.om.base.AInt8;
 import org.apache.asterix.om.base.AInterval;
 import org.apache.asterix.om.base.ALine;
+import org.apache.asterix.om.base.AMissing;
 import org.apache.asterix.om.base.ANull;
 import org.apache.asterix.om.base.AOrderedList;
 import org.apache.asterix.om.base.APoint;
@@ -91,6 +92,8 @@ public interface IOMVisitor {
 
     public void visitARecord(ARecord obj) throws AsterixException;
 
+    public void visitAMissing(AMissing obj) throws AsterixException;
+
     public void visitANull(ANull obj) throws AsterixException;
 
     public void visitAPoint(APoint obj) throws AsterixException;

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/535d86b5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/visitors/OMPrintToStringVisitor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/visitors/OMPrintToStringVisitor.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/visitors/OMPrintToStringVisitor.java
index da0e270..0752a84 100644
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/visitors/OMPrintToStringVisitor.java
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/visitors/OMPrintToStringVisitor.java
@@ -36,6 +36,7 @@ import org.apache.asterix.om.base.AInt64;
 import org.apache.asterix.om.base.AInt8;
 import org.apache.asterix.om.base.AInterval;
 import org.apache.asterix.om.base.ALine;
+import org.apache.asterix.om.base.AMissing;
 import org.apache.asterix.om.base.ANull;
 import org.apache.asterix.om.base.AOrderedList;
 import org.apache.asterix.om.base.APoint;
@@ -150,6 +151,11 @@ public class OMPrintToStringVisitor implements IOMVisitor {
     }
 
     @Override
+    public void visitAMissing(AMissing obj) throws AsterixException {
+        buffer.append("missing");
+    }
+
+    @Override
     public void visitANull(ANull obj) throws AsterixException {
         buffer.append("null");
     }
@@ -252,8 +258,8 @@ public class OMPrintToStringVisitor implements IOMVisitor {
             }
             default: {
                 // TODO Auto-generated method stub
-                throw new NotImplementedException("Pretty-printing is not 
implemented for type " + obj.getTypeTag()
-                        + " .");
+                throw new NotImplementedException(
+                        "Pretty-printing is not implemented for type " + 
obj.getTypeTag() + " .");
             }
         }
 


Reply via email to