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/07/26 21:23:21 UTC

[1/4] asterixdb git commit: Support CASE expression in SQL++.

Repository: asterixdb
Updated Branches:
  refs/heads/master f23d86e98 -> c8c067c58


http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSubstituteExpressionsVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSubstituteExpressionsVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSubstituteExpressionsVisitor.java
index af160bf..d9b2698 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSubstituteExpressionsVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSubstituteExpressionsVisitor.java
@@ -41,6 +41,7 @@ import org.apache.asterix.lang.sqlpp.clause.SelectElement;
 import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
 import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
 import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
 import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
@@ -269,4 +270,18 @@ public class SqlppSubstituteExpressionsVisitor extends SubstituteExpressionVisit
         return null;
     }
 
+    @Override
+    public Expression visit(CaseExpression caseExpr, ExpressionSubstitutionEnvironment env) throws AsterixException {
+        Expression newCaseExpr = env.findSubstitution(caseExpr, deepCopier);
+        if (newCaseExpr == caseExpr) {
+            caseExpr.setConditionExpr(caseExpr.getConditionExpr().accept(this, env));
+            caseExpr.setWhenExprs(rewriteExpressionList(caseExpr.getWhenExprs(), env));
+            caseExpr.setThenExprs(rewriteExpressionList(caseExpr.getThenExprs(), env));
+            caseExpr.setElseExpr(caseExpr.getElseExpr().accept(this, env));
+            return caseExpr;
+        } else {
+            return newCaseExpr.accept(this, env);
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppAstVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppAstVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppAstVisitor.java
index e5bf513..c0947f3 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppAstVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppAstVisitor.java
@@ -32,6 +32,7 @@ import org.apache.asterix.lang.sqlpp.clause.SelectElement;
 import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
 import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
 import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
 import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 
@@ -110,4 +111,9 @@ public abstract class AbstractSqlppAstVisitor<R, T> extends AbstractAstVisitor<R
         return null;
     }
 
+    @Override
+    public R visit(CaseExpression caseExpr, T arg) throws AsterixException {
+        return null;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
index 9fd5a6e..423eb40 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
@@ -58,6 +58,7 @@ import org.apache.asterix.lang.sqlpp.clause.SelectElement;
 import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
 import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
 import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
 import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
@@ -267,11 +268,7 @@ public class AbstractSqlppSimpleExpressionVisitor
 
     @Override
     public Expression visit(ListConstructor lc, ILangExpression arg) throws AsterixException {
-        List<Expression> newExprList = new ArrayList<>();
-        for (Expression expr : lc.getExprList()) {
-            newExprList.add(expr.accept(this, lc));
-        }
-        lc.setExprList(newExprList);
+        lc.setExprList(visit(lc.getExprList(), arg));
         return lc;
     }
 
@@ -286,11 +283,7 @@ public class AbstractSqlppSimpleExpressionVisitor
 
     @Override
     public Expression visit(OperatorExpr operatorExpr, ILangExpression arg) throws AsterixException {
-        List<Expression> newExprList = new ArrayList<>();
-        for (Expression expr : operatorExpr.getExprList()) {
-            newExprList.add(expr.accept(this, operatorExpr));
-        }
-        operatorExpr.setExprList(newExprList);
+        operatorExpr.setExprList(visit(operatorExpr.getExprList(), arg));
         return operatorExpr;
     }
 
@@ -353,4 +346,21 @@ public class AbstractSqlppSimpleExpressionVisitor
         return independentSubquery;
     }
 
+    @Override
+    public Expression visit(CaseExpression caseExpr, ILangExpression arg) throws AsterixException {
+        caseExpr.setConditionExpr(caseExpr.getConditionExpr().accept(this, arg));
+        caseExpr.setWhenExprs(visit(caseExpr.getWhenExprs(), arg));
+        caseExpr.setThenExprs(visit(caseExpr.getThenExprs(), arg));
+        caseExpr.setElseExpr(caseExpr.getElseExpr().accept(this, arg));
+        return caseExpr;
+    }
+
+    private List<Expression> visit(List<Expression> exprs, ILangExpression arg) throws AsterixException {
+        List<Expression> newExprList = new ArrayList<>();
+        for (Expression expr : exprs) {
+            newExprList.add(expr.accept(this, arg));
+        }
+        return newExprList;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/ISqlppVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/ISqlppVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/ISqlppVisitor.java
index 4e5e58d..2827e37 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/ISqlppVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/ISqlppVisitor.java
@@ -32,6 +32,7 @@ import org.apache.asterix.lang.sqlpp.clause.SelectElement;
 import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
 import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
 import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
 import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 
@@ -64,4 +65,6 @@ public interface ISqlppVisitor<R, T> extends ILangVisitor<R, T> {
     R visit(HavingClause havingClause, T arg) throws AsterixException;
 
     R visit(IndependentSubquery independentSubquery, T arg) throws AsterixException;
+
+    R visit(CaseExpression caseExpression, T arg) throws AsterixException;
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.html b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.html
index 8d093d9..7b37ab4 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.html
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.html
@@ -42,6 +42,7 @@
 | &lt;ELEMENT: "element"&gt;
 | &lt;ELSE: "else"&gt;
 | &lt;ENFORCED: "enforced"&gt;
+| &lt;END: "end"&gt;
 | &lt;EVERY: "every"&gt;
 | &lt;EXCEPT: "except"&gt;
 | &lt;EXISTS: "exists"&gt;
@@ -674,7 +675,7 @@
 <TR>
 <TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod44">Expression</A></TD>
 <TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
-<TD ALIGN=LEFT VALIGN=BASELINE>( <A HREF="#prod63">OperatorExpr</A> | <A HREF="#prod64">IfThenElse</A> | <A HREF="#prod65">QuantifiedExpression</A> )</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>( <A HREF="#prod63">OperatorExpr</A> | <A HREF="#prod64">CaseExpr</A> | <A HREF="#prod65">QuantifiedExpression</A> )</TD>
 </TR>
 <TR>
 <TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod63">OperatorExpr</A></TD>
@@ -797,9 +798,9 @@
 <TD ALIGN=LEFT VALIGN=BASELINE>( &lt;LEFTPAREN&gt; <A HREF="#prod44">Expression</A> &lt;RIGHTPAREN&gt; | <A HREF="#prod88">Subquery</A> )</TD>
 </TR>
 <TR>
-<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod64">IfThenElse</A></TD>
+<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod64">CaseExpr</A></TD>
 <TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
-<TD ALIGN=LEFT VALIGN=BASELINE>&lt;IF&gt; &lt;LEFTPAREN&gt; <A HREF="#prod44">Expression</A> &lt;RIGHTPAREN&gt; &lt;THEN&gt; <A HREF="#prod44">Expression</A> &lt;ELSE&gt; <A HREF="#prod44">Expression</A></TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>&lt;CASE&gt; ( <A HREF="#prod44">Expression</A> )? ( &lt;WHEN&gt; <A HREF="#prod44">Expression</A> &lt;THEN&gt; <A HREF="#prod44">Expression</A> )* ( &lt;ELSE&gt; <A HREF="#prod44">Expression</A> )? &lt;END&gt;</TD>
 </TR>
 <TR>
 <TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod62">SelectExpression</A></TD>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index 99b875a..d496027 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -136,6 +136,7 @@ import org.apache.asterix.lang.sqlpp.clause.SelectElement;
 import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
 import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
 import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.optype.JoinType;
 import org.apache.asterix.lang.sqlpp.optype.SetOpType;
@@ -1591,7 +1592,7 @@ Expression Expression():
 (
     LOOKAHEAD(2)
     expr = OperatorExpr()
-    | expr = IfThenElse()
+    | expr = CaseExpr()
     | expr = QuantifiedExpression()
 )
     {
@@ -2212,22 +2213,34 @@ Expression ParenthesizedExpression() throws ParseException:
     }
 }
 
-Expression IfThenElse() throws ParseException:
+
+Expression CaseExpr() throws ParseException:
 {
-  Expression condExpr;
-  Expression thenExpr;
-  Expression elseExpr;
-  IfExpr ifExpr = new IfExpr();
+   Expression conditionExpr = new LiteralExpr(TrueLiteral.INSTANCE);
+   List<Expression> whenExprs = new ArrayList<Expression>();
+   List<Expression> thenExprs = new ArrayList<Expression>();
+   Expression elseExpr = null;
+   
+   Expression whenExpr = null;
+   Expression thenExpr = null;
 }
 {
-    <IF> <LEFTPAREN> condExpr = Expression() <RIGHTPAREN> <THEN> thenExpr = Expression() <ELSE> elseExpr = Expression()
-
-    {
-      ifExpr.setCondExpr(condExpr);
-      ifExpr.setThenExpr(thenExpr);
-      ifExpr.setElseExpr(elseExpr);
-      return ifExpr;
-    }
+   <CASE> (  conditionExpr = Expression() )?
+   (
+     <WHEN> whenExpr = Expression()
+     {
+        whenExprs.add(whenExpr);
+     }
+     <THEN> thenExpr = Expression()
+     {
+        thenExprs.add(thenExpr);
+     }
+   )*
+   (<ELSE> elseExpr = Expression() )?
+   <END>
+   {
+     return new CaseExpression(conditionExpr, whenExprs, thenExprs, elseExpr);
+   }
 }
 
 SelectExpression SelectExpression(boolean subquery) throws ParseException: {
@@ -2821,6 +2834,7 @@ TOKEN [IGNORE_CASE]:
   | <ELEMENT : "element">
   | <ELSE : "else">
   | <ENFORCED : "enforced">
+  | <END : "end">
   | <EVERY : "every">
   | <EXCEPT : "except">
   | <EXISTS : "exists">

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/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 e5950e3..e303d97 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
@@ -55,8 +55,7 @@ import org.apache.asterix.om.typecomputer.impl.AYearMonthDurationTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.AnyTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.BooleanFunctionTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.BooleanOnlyTypeComputer;
-import org.apache.asterix.om.typecomputer.impl.CastListResultTypeComputer;
-import org.apache.asterix.om.typecomputer.impl.CastRecordResultTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.CastTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.ClosedRecordConstructorResultType;
 import org.apache.asterix.om.typecomputer.impl.CollectionMemberResultType;
 import org.apache.asterix.om.typecomputer.impl.CollectionToSequenceTypeComputer;
@@ -584,12 +583,10 @@ public class AsterixBuiltinFunctions {
 
     public static final FunctionIdentifier INJECT_FAILURE = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
             "inject-failure", 2);
-    public static final FunctionIdentifier CAST_RECORD = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
-            "cast-record", 1);
     public static final FunctionIdentifier FLOW_RECORD = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
             "flow-record", 1);
-    public static final FunctionIdentifier CAST_LIST = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "cast-list",
-            1);
+    public static final FunctionIdentifier CAST_TYPE = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "cast", 1);
 
     public static final FunctionIdentifier CREATE_UUID = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
             "create-uuid", 0);
@@ -942,8 +939,7 @@ public class AsterixBuiltinFunctions {
         addFunction(SWITCH_CASE, SwitchCaseComputer.INSTANCE, true);
         addPrivateFunction(REG_EXP, ABooleanTypeComputer.INSTANCE, true);
         addPrivateFunction(INJECT_FAILURE, InjectFailureTypeComputer.INSTANCE, true);
-        addPrivateFunction(CAST_RECORD, CastRecordResultTypeComputer.INSTANCE, true);
-        addPrivateFunction(CAST_LIST, CastListResultTypeComputer.INSTANCE, true);
+        addPrivateFunction(CAST_TYPE, CastTypeComputer.INSTANCE, true);
 
         addFunction(TID, AInt64TypeComputer.INSTANCE, true);
         addFunction(TIME_CONSTRUCTOR, ATimeTypeComputer.INSTANCE, true);
@@ -1416,4 +1412,4 @@ public class AsterixBuiltinFunctions {
         return similarityFunctions.contains(getAsterixFunctionInfo(fi));
     }
 
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/CastListResultTypeComputer.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/CastListResultTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/CastListResultTypeComputer.java
deleted file mode 100644
index fc4242d..0000000
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/CastListResultTypeComputer.java
+++ /dev/null
@@ -1,46 +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;
-
-/**
- * The type computer for the cast-list function
- *
- * @author yingyib
- */
-public class CastListResultTypeComputer implements IResultTypeComputer {
-
-    public static final CastListResultTypeComputer INSTANCE = new CastListResultTypeComputer();
-
-    @Override
-    public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env,
-            IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
-        ScalarFunctionCallExpression funcExpr = (ScalarFunctionCallExpression) expression;
-        return TypeCastUtils.getRequiredType(funcExpr);
-    }
-}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/CastRecordResultTypeComputer.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/CastRecordResultTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/CastRecordResultTypeComputer.java
deleted file mode 100644
index e95571b..0000000
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/CastRecordResultTypeComputer.java
+++ /dev/null
@@ -1,40 +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 CastRecordResultTypeComputer implements IResultTypeComputer {
-
-    public static final CastRecordResultTypeComputer INSTANCE = new CastRecordResultTypeComputer();
-
-    @Override
-    public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env,
-            IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
-        ScalarFunctionCallExpression funcExpr = (ScalarFunctionCallExpression) expression;
-        return TypeCastUtils.getRequiredType(funcExpr);
-    }
-}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/CastTypeComputer.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/CastTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/CastTypeComputer.java
new file mode 100644
index 0000000..64f85cb
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/CastTypeComputer.java
@@ -0,0 +1,46 @@
+/*
+ * 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;
+
+/**
+ * The type computer for the cast-list function
+ *
+ * @author yingyib
+ */
+public class CastTypeComputer implements IResultTypeComputer {
+
+    public static final CastTypeComputer INSTANCE = new CastTypeComputer();
+
+    @Override
+    public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env,
+            IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
+        ScalarFunctionCallExpression funcExpr = (ScalarFunctionCallExpression) expression;
+        return TypeCastUtils.getRequiredType(funcExpr);
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/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
index 167cb44..0eb60cb 100644
--- 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
@@ -48,19 +48,28 @@ public class SwitchCaseComputer implements IResultTypeComputer {
 
         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;
+        boolean unknownable = false;
+        int argSize = fce.getArguments().size();
+        // Checks return types of different branches' return types.
+        // The last return expression is from the ELSE branch and it is optional.
+        for (int argIndex = 2; argIndex < argSize; argIndex += (argIndex + 2 == argSize) ? 1 : 2) {
+            IAType type = (IAType) env.getType(fce.getArguments().get(argIndex).getValue());
+            ATypeTag typeTag = type.getTypeTag();
+            if (typeTag == ATypeTag.NULL || typeTag == ATypeTag.MISSING) {
+                unknownable = true;
+            } else {
+                if (typeTag == ATypeTag.UNION) {
+                    type = ((AUnionType) type).getActualType();
+                    unknownable = true;
+                }
+                if (currentType != null && !type.equals(currentType)) {
+                    any = true;
+                    break;
+                }
+                currentType = type;
             }
-            if (currentType != null && !type.equals(currentType)) {
-                any = true;
-                break;
-            }
-            currentType = type;
         }
-        return any ? BuiltinType.ANY : missable ? AUnionType.createMissableType(currentType) : currentType;
+        currentType = currentType == null ? BuiltinType.ANULL : currentType;
+        return any ? BuiltinType.ANY : unknownable ? AUnionType.createUnknownableType(currentType) : currentType;
     }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/AbstractTypeCheckEvaluator.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/AbstractTypeCheckEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/AbstractTypeCheckEvaluator.java
index 800afd7..2866f7b 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/AbstractTypeCheckEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/AbstractTypeCheckEvaluator.java
@@ -23,6 +23,7 @@ import java.io.DataOutput;
 
 import org.apache.asterix.dataflow.data.nontagged.serde.AObjectSerializerDeserializer;
 import org.apache.asterix.om.base.ABoolean;
+import org.apache.asterix.om.types.ATypeTag;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
@@ -33,6 +34,13 @@ import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
 
 public abstract class AbstractTypeCheckEvaluator implements IScalarEvaluator {
 
+    protected enum Value {
+        TRUE,
+        FALSE,
+        MISSING
+    }
+
+    private static final byte[] MISSING_BYTES = new byte[] { ATypeTag.SERIALIZED_MISSING_TYPE_TAG };
     private final ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
     private final DataOutput out = resultStorage.getDataOutput();
     private final IPointable argPtr = new VoidPointable();
@@ -46,8 +54,12 @@ public abstract class AbstractTypeCheckEvaluator implements IScalarEvaluator {
     @Override
     public void evaluate(IFrameTupleReference tuple, IPointable result) throws AlgebricksException {
         eval.evaluate(tuple, argPtr);
-        boolean match = isMatch(argPtr.getByteArray()[argPtr.getStartOffset()]);
-        ABoolean res = match ? ABoolean.TRUE : ABoolean.FALSE;
+        Value match = isMatch(argPtr.getByteArray()[argPtr.getStartOffset()]);
+        if (match == Value.MISSING) {
+            result.set(MISSING_BYTES, 0, MISSING_BYTES.length);
+            return;
+        }
+        ABoolean res = match == Value.TRUE ? ABoolean.TRUE : ABoolean.FALSE;
         try {
             resultStorage.reset();
             aObjSerDer.serialize(res, out);
@@ -57,6 +69,6 @@ public abstract class AbstractTypeCheckEvaluator implements IScalarEvaluator {
         }
     }
 
-    protected abstract boolean isMatch(byte typeTag);
+    protected abstract Value isMatch(byte typeTag);
 
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastListDescriptor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastListDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastListDescriptor.java
deleted file mode 100644
index f776d1d..0000000
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastListDescriptor.java
+++ /dev/null
@@ -1,105 +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.runtime.evaluators.functions;
-
-import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
-import org.apache.asterix.om.functions.IFunctionDescriptor;
-import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
-import org.apache.asterix.om.pointables.PointableAllocator;
-import org.apache.asterix.om.pointables.base.IVisitablePointable;
-import org.apache.asterix.om.pointables.cast.ACastVisitor;
-import org.apache.asterix.om.types.AbstractCollectionType;
-import org.apache.asterix.om.types.IAType;
-import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
-import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.common.utils.Triple;
-import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
-import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
-import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
-import org.apache.hyracks.api.context.IHyracksTaskContext;
-import org.apache.hyracks.data.std.api.IPointable;
-import org.apache.hyracks.data.std.primitive.VoidPointable;
-import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
-
-/**
- * The runtime function for casting a list(unordered list or ordered list)
- *
- * @author yingyib
- */
-public class CastListDescriptor extends AbstractScalarFunctionDynamicDescriptor {
-
-    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
-        @Override
-        public IFunctionDescriptor createFunctionDescriptor() {
-            return new CastListDescriptor();
-        }
-    };
-
-    private static final long serialVersionUID = 1L;
-    private AbstractCollectionType reqType;
-    private AbstractCollectionType inputType;
-
-    public void reset(AbstractCollectionType reqType, AbstractCollectionType inputType) {
-        this.reqType = reqType;
-        this.inputType = inputType;
-    }
-
-    @Override
-    public FunctionIdentifier getIdentifier() {
-        return AsterixBuiltinFunctions.CAST_LIST;
-    }
-
-    @Override
-    public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) {
-        final IScalarEvaluatorFactory recordEvalFactory = args[0];
-
-        return new IScalarEvaluatorFactory() {
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            public IScalarEvaluator createScalarEvaluator(IHyracksTaskContext ctx) throws AlgebricksException {
-                final IPointable recordPtr = new VoidPointable();
-                final IScalarEvaluator recEvaluator = recordEvalFactory.createScalarEvaluator(ctx);
-
-                return new IScalarEvaluator() {
-                    // pointable allocator
-                    private PointableAllocator allocator = new PointableAllocator();
-                    final IVisitablePointable recAccessor = allocator.allocateListValue(inputType);
-                    final IVisitablePointable resultAccessor = allocator.allocateListValue(reqType);
-                    final ACastVisitor castVisitor = new ACastVisitor();
-                    final Triple<IVisitablePointable, IAType, Boolean> arg = new Triple<IVisitablePointable, IAType, Boolean>(
-                            resultAccessor, reqType, Boolean.FALSE);
-
-                    @Override
-                    public void evaluate(IFrameTupleReference tuple, IPointable result) throws AlgebricksException {
-                        try {
-                            recEvaluator.evaluate(tuple, recordPtr);
-                            recAccessor.set(recordPtr);
-                            recAccessor.accept(castVisitor, arg);
-                            result.set(resultAccessor);
-                        } catch (Exception ioe) {
-                            throw new AlgebricksException(ioe);
-                        }
-                    }
-                };
-            }
-        };
-    }
-}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastRecordDescriptor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastRecordDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastRecordDescriptor.java
deleted file mode 100644
index 81e132a..0000000
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastRecordDescriptor.java
+++ /dev/null
@@ -1,102 +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.runtime.evaluators.functions;
-
-import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
-import org.apache.asterix.om.functions.IFunctionDescriptor;
-import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
-import org.apache.asterix.om.pointables.PointableAllocator;
-import org.apache.asterix.om.pointables.base.IVisitablePointable;
-import org.apache.asterix.om.pointables.cast.ACastVisitor;
-import org.apache.asterix.om.types.ARecordType;
-import org.apache.asterix.om.types.IAType;
-import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
-import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.common.utils.Triple;
-import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
-import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
-import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
-import org.apache.hyracks.api.context.IHyracksTaskContext;
-import org.apache.hyracks.data.std.api.IPointable;
-import org.apache.hyracks.data.std.primitive.VoidPointable;
-import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
-
-public class CastRecordDescriptor extends AbstractScalarFunctionDynamicDescriptor {
-
-    private CastRecordDescriptor() {
-    }
-
-    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
-        @Override
-        public IFunctionDescriptor createFunctionDescriptor() {
-            return new CastRecordDescriptor();
-        }
-    };
-
-    private static final long serialVersionUID = 1L;
-    private ARecordType reqType;
-    private ARecordType inputType;
-
-    public void reset(ARecordType reqType, ARecordType inputType) {
-        this.reqType = reqType;
-        this.inputType = inputType;
-    }
-
-    @Override
-    public FunctionIdentifier getIdentifier() {
-        return AsterixBuiltinFunctions.CAST_RECORD;
-    }
-
-    @Override
-    public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) {
-        final IScalarEvaluatorFactory recordEvalFactory = args[0];
-
-        return new IScalarEvaluatorFactory() {
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            public IScalarEvaluator createScalarEvaluator(IHyracksTaskContext ctx) throws AlgebricksException {
-                final IPointable recordPtr = new VoidPointable();
-                final IScalarEvaluator recEvaluator = recordEvalFactory.createScalarEvaluator(ctx);
-
-                return new IScalarEvaluator() {
-                    // pointable allocator
-                    private PointableAllocator allocator = new PointableAllocator();
-                    final IVisitablePointable recAccessor = allocator.allocateRecordValue(inputType);
-                    final IVisitablePointable resultAccessor = allocator.allocateRecordValue(reqType);
-                    final ACastVisitor castVisitor = new ACastVisitor();
-                    final Triple<IVisitablePointable, IAType, Boolean> arg = new Triple<>(resultAccessor, reqType,
-                            Boolean.FALSE);
-
-                    @Override
-                    public void evaluate(IFrameTupleReference tuple, IPointable result) throws AlgebricksException {
-                        try {
-                            recEvaluator.evaluate(tuple, recordPtr);
-                            recAccessor.set(recordPtr);
-                            recAccessor.accept(castVisitor, arg);
-                            result.set(resultAccessor);
-                        } catch (Exception ioe) {
-                            throw new AlgebricksException(ioe);
-                        }
-                    }
-                };
-            }
-        };
-    }
-}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastTypeDescriptor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastTypeDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastTypeDescriptor.java
new file mode 100644
index 0000000..5c754cf
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastTypeDescriptor.java
@@ -0,0 +1,154 @@
+/*
+ * 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.runtime.evaluators.functions;
+
+import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptor;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.om.pointables.PointableAllocator;
+import org.apache.asterix.om.pointables.base.DefaultOpenFieldType;
+import org.apache.asterix.om.pointables.base.IVisitablePointable;
+import org.apache.asterix.om.pointables.cast.ACastVisitor;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.common.utils.Triple;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.hyracks.data.std.api.IPointable;
+import org.apache.hyracks.data.std.primitive.VoidPointable;
+import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+/**
+ * This runtime function casts an input ADM instance of a certain type into the form
+ * that confirms a required type.
+ */
+public class CastTypeDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+
+        @Override
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new CastTypeDescriptor();
+        }
+    };
+
+    private static final long serialVersionUID = 1L;
+    private IAType reqType;
+    private IAType inputType;
+
+    private CastTypeDescriptor() {
+    }
+
+    public void reset(IAType reqType, IAType inputType) {
+        // If reqType or inputType is null, or they are the same, it indicates there is a bug in the compiler.
+        if (reqType == null || inputType == null || reqType.equals(inputType)) {
+            throw new IllegalStateException(
+                    "Invalid types for casting, required type " + reqType + ", input type " + inputType);
+        }
+        this.reqType = reqType;
+        this.inputType = inputType;
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.CAST_TYPE;
+    }
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) {
+        final IScalarEvaluatorFactory recordEvalFactory = args[0];
+
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(IHyracksTaskContext ctx) throws AlgebricksException {
+                return new CastTypeEvaluator(reqType, inputType, recordEvalFactory.createScalarEvaluator(ctx));
+            }
+        };
+    }
+}
+
+class CastTypeEvaluator implements IScalarEvaluator {
+
+    private final IScalarEvaluator argEvaluator;
+    private final IPointable argPointable = new VoidPointable();
+
+    private final PointableAllocator allocator = new PointableAllocator();
+    private final IVisitablePointable inputPointable;
+    private final IVisitablePointable resultPointable;
+
+    private final ACastVisitor castVisitor = new ACastVisitor();
+    private final Triple<IVisitablePointable, IAType, Boolean> arg;
+
+    public CastTypeEvaluator(IAType reqType, IAType inputType, IScalarEvaluator argEvaluator)
+            throws AlgebricksException {
+        try {
+            this.argEvaluator = argEvaluator;
+            this.inputPointable = allocateResultPointable(inputType, reqType);
+            this.resultPointable = allocateResultPointable(reqType, inputType);
+            this.arg = new Triple<>(resultPointable, reqType, Boolean.FALSE);
+        } catch (AsterixException e) {
+            throw new AlgebricksException(e);
+        }
+    }
+
+    @Override
+    public void evaluate(IFrameTupleReference tuple, IPointable result) throws AlgebricksException {
+        try {
+            argEvaluator.evaluate(tuple, argPointable);
+            inputPointable.set(argPointable);
+            inputPointable.accept(castVisitor, arg);
+            result.set(resultPointable);
+        } catch (Exception ioe) {
+            throw new AlgebricksException(ioe);
+        }
+    }
+
+    // Allocates the result pointable.
+    private final IVisitablePointable allocateResultPointable(IAType typeForPointable, IAType typeForOtherSide)
+            throws AsterixException {
+        if (!typeForPointable.equals(BuiltinType.ANY)) {
+            return allocator.allocateFieldValue(typeForPointable);
+        }
+        return allocatePointableForAny(typeForOtherSide);
+    }
+
+    // Allocates an input or result pointable if the input or required type is ANY.
+    private IVisitablePointable allocatePointableForAny(IAType type) {
+        ATypeTag tag = type.getTypeTag();
+        switch (tag) {
+            case RECORD:
+                return allocator.allocateFieldValue(DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE);
+            case ORDEREDLIST:
+                return allocator.allocateFieldValue(DefaultOpenFieldType.NESTED_OPEN_AORDERED_LIST_TYPE);
+            case UNORDEREDLIST:
+                return allocator.allocateFieldValue(DefaultOpenFieldType.NESTED_OPEN_AUNORDERED_LIST_TYPE);
+            default:
+                return allocator.allocateFieldValue(null);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IsMissingDescriptor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IsMissingDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IsMissingDescriptor.java
index 45c3f6d..a3bdb30 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IsMissingDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IsMissingDescriptor.java
@@ -51,8 +51,8 @@ public class IsMissingDescriptor extends AbstractScalarFunctionDynamicDescriptor
                 return new AbstractTypeCheckEvaluator(eval) {
 
                     @Override
-                    protected boolean isMatch(byte typeTag) {
-                        return typeTag == ATypeTag.SERIALIZED_MISSING_TYPE_TAG;
+                    protected Value isMatch(byte typeTag) {
+                        return typeTag == ATypeTag.SERIALIZED_MISSING_TYPE_TAG ? Value.TRUE : Value.FALSE;
                     }
                 };
             }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IsNullDescriptor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IsNullDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IsNullDescriptor.java
index 3ae3bd9..33db8f3 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IsNullDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IsNullDescriptor.java
@@ -51,8 +51,11 @@ public class IsNullDescriptor extends AbstractScalarFunctionDynamicDescriptor {
                 return new AbstractTypeCheckEvaluator(eval) {
 
                     @Override
-                    protected boolean isMatch(byte typeTag) {
-                        return typeTag == ATypeTag.SERIALIZED_NULL_TYPE_TAG;
+                    protected Value isMatch(byte typeTag) {
+                        if (typeTag == ATypeTag.SERIALIZED_MISSING_TYPE_TAG) {
+                            return Value.MISSING;
+                        }
+                        return typeTag == ATypeTag.SERIALIZED_NULL_TYPE_TAG ? Value.TRUE : Value.FALSE;
                     }
                 };
             }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IsUnknownDescriptor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IsUnknownDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IsUnknownDescriptor.java
index be04c86..ef5f42c 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IsUnknownDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IsUnknownDescriptor.java
@@ -51,9 +51,9 @@ public class IsUnknownDescriptor extends AbstractScalarFunctionDynamicDescriptor
                 return new AbstractTypeCheckEvaluator(eval) {
 
                     @Override
-                    protected boolean isMatch(byte typeTag) {
-                        return typeTag == ATypeTag.SERIALIZED_NULL_TYPE_TAG
-                                || typeTag == ATypeTag.SERIALIZED_MISSING_TYPE_TAG;
+                    protected Value isMatch(byte typeTag) {
+                        return (typeTag == ATypeTag.SERIALIZED_NULL_TYPE_TAG
+                                || typeTag == ATypeTag.SERIALIZED_MISSING_TYPE_TAG) ? Value.TRUE : Value.FALSE;
                     }
                 };
             }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/SwitchCaseDescriptor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/SwitchCaseDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/SwitchCaseDescriptor.java
index df0b973..9e14bff 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/SwitchCaseDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/SwitchCaseDescriptor.java
@@ -93,13 +93,14 @@ public class SwitchCaseDescriptor extends AbstractScalarFunctionDynamicDescripto
                     }
 
                     private boolean equals(IPointable out1, IPointable out2) {
-                        if (out1.getStartOffset() != out2.getStartOffset() || out1.getLength() != out2.getLength()) {
+                        if (out1.getLength() != out2.getLength()) {
                             return false;
                         }
                         byte[] data1 = out1.getByteArray();
                         byte[] data2 = out2.getByteArray();
-                        for (int i = out1.getStartOffset(); i < out1.getLength(); i++) {
-                            if (data1[i] != data2[i]) {
+                        for (int i = out1.getStartOffset(), j = out2.getStartOffset(), k = 0; k < out1
+                                .getLength(); ++i, ++j, ++k) {
+                            if (data1[i] != data2[j]) {
                                 return false;
                             }
                         }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java
index 64735ff..8737360 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java
@@ -60,15 +60,12 @@ 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.AbstractCollectionType;
 import org.apache.asterix.om.types.IAType;
 import org.apache.asterix.runtime.aggregates.collections.ListifyAggregateDescriptor;
 import org.apache.asterix.runtime.evaluators.common.CreateMBREvalFactory;
 import org.apache.asterix.runtime.evaluators.common.FunctionManagerImpl;
 import org.apache.asterix.runtime.evaluators.constructors.ClosedRecordConstructorDescriptor;
 import org.apache.asterix.runtime.evaluators.constructors.OpenRecordConstructorDescriptor;
-import org.apache.asterix.runtime.evaluators.functions.CastListDescriptor;
-import org.apache.asterix.runtime.evaluators.functions.CastRecordDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.OrderedListConstructorDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.UnorderedListConstructorDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.records.FieldAccessByIndexEvalFactory;
@@ -210,8 +207,8 @@ public class NonTaggedDataFormat implements IDataFormat {
                     } catch (HyracksDataException e) {
                         throw new AlgebricksException(e);
                     }
-                    IScalarEvaluatorFactory fldIndexEvalFactory = new ConstantEvalFactory(
-                            Arrays.copyOf(abvs.getByteArray(), abvs.getLength()));
+                    IScalarEvaluatorFactory fldIndexEvalFactory =
+                            new ConstantEvalFactory(Arrays.copyOf(abvs.getByteArray(), abvs.getLength()));
 
                     evalFactory = new FieldAccessByIndexEvalFactory(recordEvalFactory, fldIndexEvalFactory, recType);
                     return evalFactory;
@@ -256,8 +253,8 @@ public class NonTaggedDataFormat implements IDataFormat {
             int dimension, List<String> filterFieldName) throws AlgebricksException {
         IScalarEvaluatorFactory evalFactory = getFieldAccessEvaluatorFactory(recType, fldName, recordColumn);
         int numOfFields = dimension * 2;
-        IScalarEvaluatorFactory[] evalFactories = new IScalarEvaluatorFactory[numOfFields
-                + (filterFieldName == null ? 0 : 1)];
+        IScalarEvaluatorFactory[] evalFactories =
+                new IScalarEvaluatorFactory[numOfFields + (filterFieldName == null ? 0 : 1)];
 
         ArrayBackedValueStorage abvs1 = new ArrayBackedValueStorage();
         DataOutput dos1 = abvs1.getDataOutput();
@@ -267,8 +264,8 @@ public class NonTaggedDataFormat implements IDataFormat {
         } catch (HyracksDataException e) {
             throw new AlgebricksException(e);
         }
-        IScalarEvaluatorFactory dimensionEvalFactory = new ConstantEvalFactory(
-                Arrays.copyOf(abvs1.getByteArray(), abvs1.getLength()));
+        IScalarEvaluatorFactory dimensionEvalFactory =
+                new ConstantEvalFactory(Arrays.copyOf(abvs1.getByteArray(), abvs1.getLength()));
 
         for (int i = 0; i < numOfFields; i++) {
             ArrayBackedValueStorage abvs2 = new ArrayBackedValueStorage();
@@ -279,8 +276,8 @@ public class NonTaggedDataFormat implements IDataFormat {
             } catch (HyracksDataException e) {
                 throw new AlgebricksException(e);
             }
-            IScalarEvaluatorFactory coordinateEvalFactory = new ConstantEvalFactory(
-                    Arrays.copyOf(abvs2.getByteArray(), abvs2.getLength()));
+            IScalarEvaluatorFactory coordinateEvalFactory =
+                    new ConstantEvalFactory(Arrays.copyOf(abvs2.getByteArray(), abvs2.getLength()));
 
             evalFactories[i] = new CreateMBREvalFactory(evalFactory, dimensionEvalFactory, coordinateEvalFactory);
         }
@@ -299,8 +296,8 @@ public class NonTaggedDataFormat implements IDataFormat {
         if (fldName.size() > 1) {
             for (int i = 0; i < n; i++) {
                 if (names[i].equals(fldName.get(0))) {
-                    IScalarEvaluatorFactory recordEvalFactory = new ColumnAccessEvalFactory(
-                            GlobalConfig.DEFAULT_INPUT_DATA_COLUMN);
+                    IScalarEvaluatorFactory recordEvalFactory =
+                            new ColumnAccessEvalFactory(GlobalConfig.DEFAULT_INPUT_DATA_COLUMN);
                     ArrayBackedValueStorage abvs = new ArrayBackedValueStorage();
                     DataOutput dos = abvs.getDataOutput();
                     try {
@@ -310,10 +307,10 @@ public class NonTaggedDataFormat implements IDataFormat {
                     } catch (HyracksDataException e) {
                         throw new AlgebricksException(e);
                     }
-                    IScalarEvaluatorFactory fldIndexEvalFactory = new ConstantEvalFactory(
-                            Arrays.copyOf(abvs.getByteArray(), abvs.getLength()));
-                    IScalarEvaluatorFactory evalFactory = new FieldAccessByIndexEvalFactory(recordEvalFactory,
-                            fldIndexEvalFactory, recType);
+                    IScalarEvaluatorFactory fldIndexEvalFactory =
+                            new ConstantEvalFactory(Arrays.copyOf(abvs.getByteArray(), abvs.getLength()));
+                    IScalarEvaluatorFactory evalFactory =
+                            new FieldAccessByIndexEvalFactory(recordEvalFactory, fldIndexEvalFactory, recType);
                     IFunctionInfo finfoAccess = AsterixBuiltinFunctions
                             .getAsterixFunctionInfo(AsterixBuiltinFunctions.FIELD_ACCESS_BY_INDEX);
 
@@ -326,8 +323,8 @@ public class NonTaggedDataFormat implements IDataFormat {
                 }
             }
         } else {
-            IScalarEvaluatorFactory recordEvalFactory = new ColumnAccessEvalFactory(
-                    GlobalConfig.DEFAULT_INPUT_DATA_COLUMN);
+            IScalarEvaluatorFactory recordEvalFactory =
+                    new ColumnAccessEvalFactory(GlobalConfig.DEFAULT_INPUT_DATA_COLUMN);
             ArrayBackedValueStorage abvs = new ArrayBackedValueStorage();
             DataOutput dos = abvs.getDataOutput();
             AOrderedList as = new AOrderedList(fldName);
@@ -337,8 +334,8 @@ public class NonTaggedDataFormat implements IDataFormat {
                 throw new AlgebricksException(e);
             }
             IScalarEvaluatorFactory evalFactory = new FieldAccessNestedEvalFactory(recordEvalFactory, recType, fldName);
-            IFunctionInfo finfoAccess = AsterixBuiltinFunctions
-                    .getAsterixFunctionInfo(AsterixBuiltinFunctions.FIELD_ACCESS_NESTED);
+            IFunctionInfo finfoAccess =
+                    AsterixBuiltinFunctions.getAsterixFunctionInfo(AsterixBuiltinFunctions.FIELD_ACCESS_NESTED);
 
             ScalarFunctionCallExpression partitionFun = new ScalarFunctionCallExpression(finfoAccess,
                     new MutableObject<ILogicalExpression>(new VariableReferenceExpression(METADATA_DUMMY_VAR)),
@@ -445,31 +442,15 @@ public class NonTaggedDataFormat implements IDataFormat {
                         + " org.apache.asterix.om.types.IAType)", outType, type0, type1);
             }
         });
-
-        functionTypeInferers.put(AsterixBuiltinFunctions.CAST_RECORD, new FunctionTypeInferer() {
-            @Override
-            public void infer(ILogicalExpression expr, IFunctionDescriptor fd, IVariableTypeEnvironment context)
-                    throws AlgebricksException {
-                AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
-                ARecordType rt = (ARecordType) TypeCastUtils.getRequiredType(funcExpr);
-                IAType it = (IAType) context.getType(funcExpr.getArguments().get(0).getValue());
-                if (it.getTypeTag().equals(ATypeTag.ANY)) {
-                    it = DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE;
-                }
-                ((CastRecordDescriptor) fd).reset(rt, (ARecordType) it);
-            }
-        });
-        functionTypeInferers.put(AsterixBuiltinFunctions.CAST_LIST, new FunctionTypeInferer() {
+        functionTypeInferers.put(AsterixBuiltinFunctions.CAST_TYPE, new FunctionTypeInferer() {
             @Override
             public void infer(ILogicalExpression expr, IFunctionDescriptor fd, IVariableTypeEnvironment context)
                     throws AlgebricksException {
                 AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
-                AbstractCollectionType rt = (AbstractCollectionType) TypeCastUtils.getRequiredType(funcExpr);
+                IAType rt = TypeCastUtils.getRequiredType(funcExpr);
                 IAType it = (IAType) context.getType(funcExpr.getArguments().get(0).getValue());
-                if (it.getTypeTag().equals(ATypeTag.ANY)) {
-                    it = DefaultOpenFieldType.NESTED_OPEN_AORDERED_LIST_TYPE;
-                }
-                ((CastListDescriptor) fd).reset(rt, (AbstractCollectionType) it);
+                PA.invokeMethod(fd, "reset(org.apache.asterix.om.types.IAType, org.apache.asterix.om.types.IAType)", rt,
+                        it);
             }
         });
         functionTypeInferers.put(AsterixBuiltinFunctions.OPEN_RECORD_CONSTRUCTOR, new FunctionTypeInferer() {
@@ -488,8 +469,9 @@ public class NonTaggedDataFormat implements IDataFormat {
                     Mutable<ILogicalExpression> argRef = expr.getArguments().get(2 * i);
                     ILogicalExpression arg = argRef.getValue();
                     if (arg.getExpressionTag() == LogicalExpressionTag.CONSTANT) {
-                        String fn = ((AString) ((AsterixConstantValue) ((ConstantExpression) arg).getValue())
-                                .getObject()).getStringValue();
+                        String fn =
+                                ((AString) ((AsterixConstantValue) ((ConstantExpression) arg).getValue()).getObject())
+                                        .getStringValue();
                         open[i] = true;
                         for (String s : recType.getFieldNames()) {
                             if (s.equals(fn)) {


[2/4] asterixdb git commit: Support CASE expression in SQL++.

Posted by bu...@apache.org.
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/query-ASTERIXDB-819/query-ASTERIXDB-819.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/query-ASTERIXDB-819/query-ASTERIXDB-819.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/query-ASTERIXDB-819/query-ASTERIXDB-819.1.adm
new file mode 100644
index 0000000..19765bd
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/query-ASTERIXDB-819/query-ASTERIXDB-819.1.adm
@@ -0,0 +1 @@
+null

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/is/is.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/is/is.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/is/is.1.adm
index 79a9c5c..38de473 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/is/is.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/is/is.1.adm
@@ -1 +1 @@
-{ "1": true, "2": false, "3": false, "4": false, "5": true, "6": true, "7": false, "8": true, "9": false, "10": true, "11": false, "12": true, "13": true, "14": true, "15": false, "16": false, "17": false, "18": true }
+{ "1": true, "3": false, "4": false, "6": true, "7": false, "8": true, "9": false, "10": true, "11": false, "12": true, "13": true, "14": true, "15": false, "16": false, "17": false, "18": true }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/misc/ifthenelse_01/ifthenelse_01.3.ast
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/misc/ifthenelse_01/ifthenelse_01.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/misc/ifthenelse_01/ifthenelse_01.3.ast
index 2223305..f16c720 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/misc/ifthenelse_01/ifthenelse_01.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/misc/ifthenelse_01/ifthenelse_01.3.ast
@@ -1,16 +1,16 @@
 DataverseUse test
 Query:
 SELECT ELEMENT [
-IfExpr [
-  Condition:
-    OperatorExpr [
+CASE    OperatorExpr [
       LiteralExpr [LONG] [2]
       >
       LiteralExpr [LONG] [1]
     ]
-  Then:
-    LiteralExpr [LONG] [20]
-  Else:
-    LiteralExpr [LONG] [10]
-]
+
+WHEN     LiteralExpr [TRUE]
+THEN     LiteralExpr [LONG] [20]
+
+ELSE     LiteralExpr [LONG] [10]
+
+END
 ]

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q08_national_market_share/q08_national_market_share.3.ast
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q08_national_market_share/q08_national_market_share.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q08_national_market_share/q08_national_market_share.3.ast
index 279175b..1292f1a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q08_national_market_share/q08_national_market_share.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q08_national_market_share/q08_national_market_share.3.ast
@@ -14,23 +14,24 @@ RecordConstructor [
       FunctionCall tpch.sum@1[
         (
           SELECT ELEMENT [
-          FunctionCall tpch.switch-case@5[
-            OperatorExpr [
-              FieldAccessor [
+          CASE              LiteralExpr [TRUE]
+
+          WHEN               OperatorExpr [
+                FieldAccessor [
+                  Variable [ Name=$i ]
+                  Field=s_name
+                ]
+                =
+                LiteralExpr [STRING] [BRAZIL]
+              ]
+          THEN               FieldAccessor [
                 Variable [ Name=$i ]
-                Field=s_name
+                Field=revenue
               ]
-              =
-              LiteralExpr [STRING] [BRAZIL]
-            ]
-            LiteralExpr [TRUE]
-            FieldAccessor [
-              Variable [ Name=$i ]
-              Field=revenue
-            ]
-            LiteralExpr [FALSE]
-            LiteralExpr [DOUBLE] [0.0]
-          ]
+
+          ELSE               LiteralExpr [DOUBLE] [0.0]
+
+          END
           ]
           FROM [            Variable [ Name=$t ]
             AS Variable [ Name=$i ]

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.ast
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.ast
index b1fee8a..3da470a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.ast
@@ -13,31 +13,35 @@ RecordConstructor [
     FunctionCall tpch.sum@1[
       (
         SELECT ELEMENT [
-        FunctionCall tpch.switch-case@5[
-          OperatorExpr [
-            OperatorExpr [
-              FieldAccessor [
-                Variable [ Name=$i ]
-                Field=o_orderpriority
+        CASE            OperatorExpr [
+              OperatorExpr [
+                FieldAccessor [
+                  Variable [ Name=$i ]
+                  Field=o_orderpriority
+                ]
+                =
+                LiteralExpr [STRING] [1-URGENT]
               ]
-              =
-              LiteralExpr [STRING] [1-URGENT]
-            ]
-            or
-            OperatorExpr [
-              FieldAccessor [
-                Variable [ Name=$i ]
-                Field=o_orderpriority
+              or
+              OperatorExpr [
+                FieldAccessor [
+                  Variable [ Name=$i ]
+                  Field=o_orderpriority
+                ]
+                =
+                LiteralExpr [STRING] [2-HIGH]
               ]
-              =
-              LiteralExpr [STRING] [2-HIGH]
             ]
-          ]
-          LiteralExpr [TRUE]
-          LiteralExpr [LONG] [1]
-          LiteralExpr [FALSE]
-          LiteralExpr [LONG] [0]
-        ]
+
+        WHEN             LiteralExpr [TRUE]
+        THEN             LiteralExpr [LONG] [1]
+
+        WHEN             LiteralExpr [FALSE]
+        THEN             LiteralExpr [LONG] [0]
+
+        ELSE             LiteralExpr [NULL]
+
+        END
         ]
         FROM [          Variable [ Name=$o ]
           AS Variable [ Name=$i ]
@@ -51,31 +55,35 @@ RecordConstructor [
     FunctionCall tpch.sum@1[
       (
         SELECT ELEMENT [
-        FunctionCall tpch.switch-case@5[
-          OperatorExpr [
-            OperatorExpr [
-              FieldAccessor [
-                Variable [ Name=$i ]
-                Field=o_orderpriority
+        CASE            OperatorExpr [
+              OperatorExpr [
+                FieldAccessor [
+                  Variable [ Name=$i ]
+                  Field=o_orderpriority
+                ]
+                =
+                LiteralExpr [STRING] [1-URGENT]
               ]
-              =
-              LiteralExpr [STRING] [1-URGENT]
-            ]
-            or
-            OperatorExpr [
-              FieldAccessor [
-                Variable [ Name=$i ]
-                Field=o_orderpriority
+              or
+              OperatorExpr [
+                FieldAccessor [
+                  Variable [ Name=$i ]
+                  Field=o_orderpriority
+                ]
+                =
+                LiteralExpr [STRING] [2-HIGH]
               ]
-              =
-              LiteralExpr [STRING] [2-HIGH]
             ]
-          ]
-          LiteralExpr [TRUE]
-          LiteralExpr [LONG] [0]
-          LiteralExpr [FALSE]
-          LiteralExpr [LONG] [1]
-        ]
+
+        WHEN             LiteralExpr [TRUE]
+        THEN             LiteralExpr [LONG] [0]
+
+        WHEN             LiteralExpr [FALSE]
+        THEN             LiteralExpr [LONG] [1]
+
+        ELSE             LiteralExpr [NULL]
+
+        END
         ]
         FROM [          Variable [ Name=$o ]
           AS Variable [ Name=$i ]

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.ast
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.ast
index f9f5c62..1bd404d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.ast
@@ -7,34 +7,38 @@ OperatorExpr [
   FunctionCall tpch.sum@1[
     (
       SELECT ELEMENT [
-      FunctionCall tpch.switch-case@5[
-        OperatorExpr [
-          FieldAccessor [
-            Variable [ Name=$i ]
-            Field=p_type
-          ]
-          like
-          LiteralExpr [STRING] [PROMO%]
-        ]
-        LiteralExpr [TRUE]
-        OperatorExpr [
-          FieldAccessor [
-            Variable [ Name=$i ]
-            Field=l_extendedprice
+      CASE          OperatorExpr [
+            FieldAccessor [
+              Variable [ Name=$i ]
+              Field=p_type
+            ]
+            like
+            LiteralExpr [STRING] [PROMO%]
           ]
-          *
-          OperatorExpr [
-            LiteralExpr [LONG] [1]
-            -
+
+      WHEN           LiteralExpr [TRUE]
+      THEN           OperatorExpr [
             FieldAccessor [
               Variable [ Name=$i ]
-              Field=l_discount
+              Field=l_extendedprice
+            ]
+            *
+            OperatorExpr [
+              LiteralExpr [LONG] [1]
+              -
+              FieldAccessor [
+                Variable [ Name=$i ]
+                Field=l_discount
+              ]
             ]
           ]
-        ]
-        LiteralExpr [FALSE]
-        LiteralExpr [DOUBLE] [0.0]
-      ]
+
+      WHEN           LiteralExpr [FALSE]
+      THEN           LiteralExpr [DOUBLE] [0.0]
+
+      ELSE           LiteralExpr [NULL]
+
+      END
       ]
       FROM [        Variable [ Name=$lp ]
         AS Variable [ Name=$i ]

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q08_national_market_share/q08_national_market_share.3.ast
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q08_national_market_share/q08_national_market_share.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q08_national_market_share/q08_national_market_share.3.ast
index 279175b..53bdb44 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q08_national_market_share/q08_national_market_share.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q08_national_market_share/q08_national_market_share.3.ast
@@ -14,23 +14,27 @@ RecordConstructor [
       FunctionCall tpch.sum@1[
         (
           SELECT ELEMENT [
-          FunctionCall tpch.switch-case@5[
-            OperatorExpr [
-              FieldAccessor [
+          CASE              OperatorExpr [
+                FieldAccessor [
+                  Variable [ Name=$i ]
+                  Field=s_name
+                ]
+                =
+                LiteralExpr [STRING] [BRAZIL]
+              ]
+
+          WHEN               LiteralExpr [TRUE]
+          THEN               FieldAccessor [
                 Variable [ Name=$i ]
-                Field=s_name
+                Field=revenue
               ]
-              =
-              LiteralExpr [STRING] [BRAZIL]
-            ]
-            LiteralExpr [TRUE]
-            FieldAccessor [
-              Variable [ Name=$i ]
-              Field=revenue
-            ]
-            LiteralExpr [FALSE]
-            LiteralExpr [DOUBLE] [0.0]
-          ]
+
+          WHEN               LiteralExpr [FALSE]
+          THEN               LiteralExpr [DOUBLE] [0.0]
+
+          ELSE               LiteralExpr [NULL]
+
+          END
           ]
           FROM [            Variable [ Name=$t ]
             AS Variable [ Name=$i ]

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q12_shipping/q12_shipping.3.ast
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q12_shipping/q12_shipping.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q12_shipping/q12_shipping.3.ast
index b1fee8a..6ad3a5b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q12_shipping/q12_shipping.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q12_shipping/q12_shipping.3.ast
@@ -13,31 +13,35 @@ RecordConstructor [
     FunctionCall tpch.sum@1[
       (
         SELECT ELEMENT [
-        FunctionCall tpch.switch-case@5[
-          OperatorExpr [
-            OperatorExpr [
-              FieldAccessor [
-                Variable [ Name=$i ]
-                Field=o_orderpriority
+        CASE            OperatorExpr [
+              OperatorExpr [
+                FieldAccessor [
+                  Variable [ Name=$i ]
+                  Field=o_orderpriority
+                ]
+                =
+                LiteralExpr [STRING] [1-URGENT]
               ]
-              =
-              LiteralExpr [STRING] [1-URGENT]
-            ]
-            or
-            OperatorExpr [
-              FieldAccessor [
-                Variable [ Name=$i ]
-                Field=o_orderpriority
+              or
+              OperatorExpr [
+                FieldAccessor [
+                  Variable [ Name=$i ]
+                  Field=o_orderpriority
+                ]
+                =
+                LiteralExpr [STRING] [2-HIGH]
               ]
-              =
-              LiteralExpr [STRING] [2-HIGH]
             ]
-          ]
-          LiteralExpr [TRUE]
-          LiteralExpr [LONG] [1]
-          LiteralExpr [FALSE]
-          LiteralExpr [LONG] [0]
-        ]
+
+        WHEN             LiteralExpr [TRUE]
+        THEN             LiteralExpr [LONG] [1]
+
+        WHEN             LiteralExpr [FALSE]
+        THEN             LiteralExpr [LONG] [0]
+
+        ELSE             LiteralExpr [NULL]
+
+        END
         ]
         FROM [          Variable [ Name=$o ]
           AS Variable [ Name=$i ]
@@ -51,31 +55,32 @@ RecordConstructor [
     FunctionCall tpch.sum@1[
       (
         SELECT ELEMENT [
-        FunctionCall tpch.switch-case@5[
-          OperatorExpr [
-            OperatorExpr [
-              FieldAccessor [
-                Variable [ Name=$i ]
-                Field=o_orderpriority
+        CASE            LiteralExpr [TRUE]
+
+        WHEN             OperatorExpr [
+              OperatorExpr [
+                FieldAccessor [
+                  Variable [ Name=$i ]
+                  Field=o_orderpriority
+                ]
+                =
+                LiteralExpr [STRING] [1-URGENT]
               ]
-              =
-              LiteralExpr [STRING] [1-URGENT]
-            ]
-            or
-            OperatorExpr [
-              FieldAccessor [
-                Variable [ Name=$i ]
-                Field=o_orderpriority
+              or
+              OperatorExpr [
+                FieldAccessor [
+                  Variable [ Name=$i ]
+                  Field=o_orderpriority
+                ]
+                =
+                LiteralExpr [STRING] [2-HIGH]
               ]
-              =
-              LiteralExpr [STRING] [2-HIGH]
             ]
-          ]
-          LiteralExpr [TRUE]
-          LiteralExpr [LONG] [0]
-          LiteralExpr [FALSE]
-          LiteralExpr [LONG] [1]
-        ]
+        THEN             LiteralExpr [LONG] [0]
+
+        ELSE             LiteralExpr [LONG] [1]
+
+        END
         ]
         FROM [          Variable [ Name=$o ]
           AS Variable [ Name=$i ]

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.ast
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.ast
index f9f5c62..f619293 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.ast
@@ -7,34 +7,35 @@ OperatorExpr [
   FunctionCall tpch.sum@1[
     (
       SELECT ELEMENT [
-      FunctionCall tpch.switch-case@5[
-        OperatorExpr [
-          FieldAccessor [
-            Variable [ Name=$i ]
-            Field=p_type
-          ]
-          like
-          LiteralExpr [STRING] [PROMO%]
-        ]
-        LiteralExpr [TRUE]
-        OperatorExpr [
-          FieldAccessor [
-            Variable [ Name=$i ]
-            Field=l_extendedprice
+      CASE          OperatorExpr [
+            FieldAccessor [
+              Variable [ Name=$i ]
+              Field=p_type
+            ]
+            like
+            LiteralExpr [STRING] [PROMO%]
           ]
-          *
-          OperatorExpr [
-            LiteralExpr [LONG] [1]
-            -
+
+      WHEN           LiteralExpr [TRUE]
+      THEN           OperatorExpr [
             FieldAccessor [
               Variable [ Name=$i ]
-              Field=l_discount
+              Field=l_extendedprice
+            ]
+            *
+            OperatorExpr [
+              LiteralExpr [LONG] [1]
+              -
+              FieldAccessor [
+                Variable [ Name=$i ]
+                Field=l_discount
+              ]
             ]
           ]
-        ]
-        LiteralExpr [FALSE]
-        LiteralExpr [DOUBLE] [0.0]
-      ]
+
+      ELSE           LiteralExpr [DOUBLE] [0.0]
+
+      END
       ]
       FROM [        Variable [ Name=$lp ]
         AS Variable [ Name=$i ]

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
index 30e99e6..279522a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
@@ -3166,6 +3166,11 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="misc">
+      <compilation-unit name="ifthenelse_02">
+        <output-dir compare="Text">ifthenelse_02</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="misc">
       <compilation-unit name="is-null_01">
         <output-dir compare="Text">is-null_01</output-dir>
       </compilation-unit>
@@ -3224,6 +3229,16 @@
         <output-dir compare="Text">query-ASTERIXDB-1203</output-dir>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="misc">
+      <compilation-unit name="query-ASTERIXDB-819">
+        <output-dir compare="Text">query-ASTERIXDB-819</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="misc">
+      <compilation-unit name="query-ASTERIXDB-819-2">
+        <output-dir compare="Text">query-ASTERIXDB-819-2</output-dir>
+      </compilation-unit>
+    </test-case>
   </test-group>
   <test-group name="open-index-enforced">
     <test-group name="open-index-enforced/error-checking">

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
index e1d728d..748d924 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -2862,6 +2862,41 @@
   </test-group>
   <test-group name="misc">
     <test-case FilePath="misc">
+      <compilation-unit name="case_01">
+        <output-dir compare="Text">case_01</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="misc">
+      <compilation-unit name="case_02">
+        <output-dir compare="Text">case_02</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="misc">
+      <compilation-unit name="case_03">
+        <output-dir compare="Text">case_03</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="misc">
+      <compilation-unit name="case_04">
+        <output-dir compare="Text">case_04</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="misc">
+      <compilation-unit name="case_05">
+        <output-dir compare="Text">case_05</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="misc">
+      <compilation-unit name="case_06">
+        <output-dir compare="Text">case_06</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="misc">
+      <compilation-unit name="case_07">
+        <output-dir compare="Text">case_05</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="misc">
       <compilation-unit name="partition-by-nonexistent-field">
         <output-dir compare="Text">partition-by-nonexistent-field</output-dir>
         <expected-error>java.lang.NullPointerException</expected-error>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/AQLInlineUdfsVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/AQLInlineUdfsVisitor.java b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/AQLInlineUdfsVisitor.java
index dd1a1fb..e0579f3 100644
--- a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/AQLInlineUdfsVisitor.java
+++ b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/AQLInlineUdfsVisitor.java
@@ -68,14 +68,14 @@ public class AQLInlineUdfsVisitor extends AbstractInlineUdfsVisitor
 
     @Override
     public Boolean visit(UnionExpr u, List<FunctionDecl> fds) throws AsterixException {
-        Pair<Boolean, ArrayList<Expression>> p = inlineUdfsInExprList(u.getExprs(), fds);
+        Pair<Boolean, List<Expression>> p = inlineUdfsInExprList(u.getExprs(), fds);
         u.setExprs(p.second);
         return p.first;
     }
 
     @Override
     public Boolean visit(DistinctClause dc, List<FunctionDecl> arg) throws AsterixException {
-        Pair<Boolean, ArrayList<Expression>> p = inlineUdfsInExprList(dc.getDistinctByExpr(), arg);
+        Pair<Boolean, List<Expression>> p = inlineUdfsInExprList(dc.getDistinctByExpr(), arg);
         dc.setDistinctByExpr(p.second);
         return p.first;
     }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/Expression.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/Expression.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/Expression.java
index 6b77fc7..b1df329 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/Expression.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/Expression.java
@@ -39,7 +39,8 @@ public interface Expression extends ILangExpression {
         SELECT_EXPRESSION,
         PRIMARY_EXPRESSION,
         VALUE_EXPRESSION,
-        INDEPENDENT_SUBQUERY
+        INDEPENDENT_SUBQUERY,
+        CASE_EXPRESSION
     }
 
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
index e76436a..159af9f 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
@@ -103,7 +103,7 @@ public abstract class AbstractInlineUdfsVisitor extends AbstractQueryExpressionV
 
     @Override
     public Boolean visit(ListConstructor lc, List<FunctionDecl> arg) throws AsterixException {
-        Pair<Boolean, ArrayList<Expression>> p = inlineUdfsInExprList(lc.getExprList(), arg);
+        Pair<Boolean, List<Expression>> p = inlineUdfsInExprList(lc.getExprList(), arg);
         lc.setExprList(p.second);
         return p.first;
     }
@@ -114,24 +114,24 @@ public abstract class AbstractInlineUdfsVisitor extends AbstractQueryExpressionV
         for (FieldBinding b : rc.getFbList()) {
             Pair<Boolean, Expression> leftExprInlined = inlineUdfsInExpr(b.getLeftExpr(), arg);
             b.setLeftExpr(leftExprInlined.second);
-            changed = changed | leftExprInlined.first;
+            changed = changed || leftExprInlined.first;
             Pair<Boolean, Expression> rightExprInlined = inlineUdfsInExpr(b.getRightExpr(), arg);
             b.setRightExpr(rightExprInlined.second);
-            changed = changed | rightExprInlined.first;
+            changed = changed || rightExprInlined.first;
         }
         return changed;
     }
 
     @Override
     public Boolean visit(CallExpr pf, List<FunctionDecl> arg) throws AsterixException {
-        Pair<Boolean, ArrayList<Expression>> p = inlineUdfsInExprList(pf.getExprList(), arg);
+        Pair<Boolean, List<Expression>> p = inlineUdfsInExprList(pf.getExprList(), arg);
         pf.setExprList(p.second);
         return p.first;
     }
 
     @Override
     public Boolean visit(OperatorExpr ifbo, List<FunctionDecl> arg) throws AsterixException {
-        Pair<Boolean, ArrayList<Expression>> p = inlineUdfsInExprList(ifbo.getExprList(), arg);
+        Pair<Boolean, List<Expression>> p = inlineUdfsInExprList(ifbo.getExprList(), arg);
         ifbo.setExprList(p.second);
         return p.first;
     }
@@ -192,7 +192,7 @@ public abstract class AbstractInlineUdfsVisitor extends AbstractQueryExpressionV
 
     @Override
     public Boolean visit(OrderbyClause oc, List<FunctionDecl> arg) throws AsterixException {
-        Pair<Boolean, ArrayList<Expression>> p = inlineUdfsInExprList(oc.getOrderbyList(), arg);
+        Pair<Boolean, List<Expression>> p = inlineUdfsInExprList(oc.getOrderbyList(), arg);
         oc.setOrderbyList(p.second);
         return p.first;
     }
@@ -249,53 +249,52 @@ public abstract class AbstractInlineUdfsVisitor extends AbstractQueryExpressionV
             throws AsterixException {
         if (expr.getKind() != Kind.CALL_EXPRESSION) {
             boolean r = expr.accept(this, arg);
-            return new Pair<Boolean, Expression>(r, expr);
+            return new Pair<>(r, expr);
+        }
+        CallExpr f = (CallExpr) expr;
+        boolean r = expr.accept(this, arg);
+        FunctionDecl implem = findFuncDeclaration(f.getFunctionSignature(), arg);
+        if (implem == null) {
+            return new Pair<>(r, expr);
         } else {
-            CallExpr f = (CallExpr) expr;
-            boolean r = expr.accept(this, arg);
-            FunctionDecl implem = findFuncDeclaration(f.getFunctionSignature(), arg);
-            if (implem == null) {
-                return new Pair<Boolean, Expression>(r, expr);
-            } else {
-                // Rewrite the function body itself (without setting unbounded variables to dataset access).
-                // TODO(buyingyi): throw an exception for recursive function definition or limit the stack depth.
-                implem.setFuncBody(rewriteFunctionBody(implem.getFuncBody()));
-                // it's one of the functions we want to inline
-                List<LetClause> clauses = new ArrayList<LetClause>();
-                Iterator<VarIdentifier> paramIter = implem.getParamList().iterator();
-                VariableSubstitutionEnvironment subts = new VariableSubstitutionEnvironment();
-                for (Expression e : f.getExprList()) {
-                    VarIdentifier param = paramIter.next();
-                    // Obs: we could do smth about passing also literals, or let
-                    // variable inlining to take care of this.
-                    if (e.getKind() == Kind.VARIABLE_EXPRESSION) {
-                        subts.addSubstituion(new VariableExpr(param), e);
-                    } else {
-                        VarIdentifier newV = context.newVariable();
-                        Pair<ILangExpression, VariableSubstitutionEnvironment> p1 = e.accept(cloneVisitor,
-                                new VariableSubstitutionEnvironment());
-                        LetClause c = new LetClause(new VariableExpr(newV), (Expression) p1.first);
-                        clauses.add(c);
-                        subts.addSubstituion(new VariableExpr(param), new VariableExpr(newV));
-                    }
-                }
-
-                Pair<ILangExpression, VariableSubstitutionEnvironment> p2 = implem.getFuncBody().accept(cloneVisitor,
-                        subts);
-                Expression resExpr;
-                if (clauses.isEmpty()) {
-                    resExpr = (Expression) p2.first;
+            // Rewrite the function body itself (without setting unbounded variables to dataset access).
+            // TODO(buyingyi): throw an exception for recursive function definition or limit the stack depth.
+            implem.setFuncBody(rewriteFunctionBody(implem.getFuncBody()));
+            // it's one of the functions we want to inline
+            List<LetClause> clauses = new ArrayList<>();
+            Iterator<VarIdentifier> paramIter = implem.getParamList().iterator();
+            VariableSubstitutionEnvironment subts = new VariableSubstitutionEnvironment();
+            for (Expression e : f.getExprList()) {
+                VarIdentifier param = paramIter.next();
+                // Obs: we could do smth about passing also literals, or let
+                // variable inlining to take care of this.
+                if (e.getKind() == Kind.VARIABLE_EXPRESSION) {
+                    subts.addSubstituion(new VariableExpr(param), e);
                 } else {
-                    resExpr = generateQueryExpression(clauses, (Expression) p2.first);
+                    VarIdentifier newV = context.newVariable();
+                    Pair<ILangExpression, VariableSubstitutionEnvironment> p1 =
+                            e.accept(cloneVisitor, new VariableSubstitutionEnvironment());
+                    LetClause c = new LetClause(new VariableExpr(newV), (Expression) p1.first);
+                    clauses.add(c);
+                    subts.addSubstituion(new VariableExpr(param), new VariableExpr(newV));
                 }
-                return new Pair<Boolean, Expression>(true, resExpr);
             }
+
+            Pair<ILangExpression, VariableSubstitutionEnvironment> p2 =
+                    implem.getFuncBody().accept(cloneVisitor, subts);
+            Expression resExpr;
+            if (clauses.isEmpty()) {
+                resExpr = (Expression) p2.first;
+            } else {
+                resExpr = generateQueryExpression(clauses, (Expression) p2.first);
+            }
+            return new Pair<>(true, resExpr);
         }
     }
 
-    protected Pair<Boolean, ArrayList<Expression>> inlineUdfsInExprList(List<Expression> exprList,
-            List<FunctionDecl> fds) throws AsterixException {
-        ArrayList<Expression> newList = new ArrayList<Expression>();
+    protected Pair<Boolean, List<Expression>> inlineUdfsInExprList(List<Expression> exprList, List<FunctionDecl> fds)
+            throws AsterixException {
+        ArrayList<Expression> newList = new ArrayList<>();
         boolean changed = false;
         for (Expression e : exprList) {
             Pair<Boolean, Expression> p = inlineUdfsInExpr(e, fds);
@@ -304,7 +303,7 @@ public abstract class AbstractInlineUdfsVisitor extends AbstractQueryExpressionV
                 changed = true;
             }
         }
-        return new Pair<Boolean, ArrayList<Expression>>(changed, newList);
+        return new Pair<>(changed, newList);
     }
 
     protected Expression rewriteFunctionBody(Expression expr) throws AsterixException {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/SubstituteExpressionVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/SubstituteExpressionVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/SubstituteExpressionVisitor.java
index 1fd561e..073e413 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/SubstituteExpressionVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/SubstituteExpressionVisitor.java
@@ -48,7 +48,7 @@ import org.apache.asterix.lang.common.visitor.base.AbstractQueryExpressionVisito
 
 public abstract class SubstituteExpressionVisitor
         extends AbstractQueryExpressionVisitor<Expression, ExpressionSubstitutionEnvironment> {
-    private final DeepCopier deepCopier;
+    protected final DeepCopier deepCopier;
 
     public SubstituteExpressionVisitor(DeepCopier deepCopier) {
         this.deepCopier = deepCopier;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/CaseExpression.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/CaseExpression.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/CaseExpression.java
new file mode 100644
index 0000000..45ff082
--- /dev/null
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/CaseExpression.java
@@ -0,0 +1,129 @@
+/*
+ * 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.lang.sqlpp.expression;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.lang.common.base.Expression;
+import org.apache.asterix.lang.common.expression.LiteralExpr;
+import org.apache.asterix.lang.common.literal.NullLiteral;
+import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
+import org.apache.asterix.lang.sqlpp.visitor.base.ISqlppVisitor;
+import org.apache.commons.lang3.ObjectUtils;
+
+public class CaseExpression implements Expression {
+
+    private Expression conditionExpr;
+    private List<Expression> whenExprs = new ArrayList<>();
+    private List<Expression> thenExprs = new ArrayList<>();
+    private Expression elseExpr; // elseExpr could be null.
+
+    public CaseExpression(Expression conditionExpr, List<Expression> whenExprs, List<Expression> thenExprs,
+            Expression elseExpr) {
+        this.conditionExpr = conditionExpr;
+        this.whenExprs.addAll(whenExprs);
+        this.thenExprs.addAll(thenExprs);
+
+        // If no when expression matches the case expr, we return null
+        this.elseExpr = elseExpr == null ? new LiteralExpr(NullLiteral.INSTANCE) : elseExpr;
+    }
+
+    @Override
+    public <R, T> R accept(ILangVisitor<R, T> visitor, T arg) throws AsterixException {
+        return ((ISqlppVisitor<R, T>) visitor).visit(this, arg);
+    }
+
+    @Override
+    public Kind getKind() {
+        return Kind.CASE_EXPRESSION;
+    }
+
+    public Expression getConditionExpr() {
+        return conditionExpr;
+    }
+
+    public Expression getElseExpr() {
+        return elseExpr;
+    }
+
+    public List<Expression> getWhenExprs() {
+        return whenExprs;
+    }
+
+    public List<Expression> getThenExprs() {
+        return thenExprs;
+    }
+
+    public void setConditionExpr(Expression conditionExpr) {
+        this.conditionExpr = conditionExpr;
+    }
+
+    public void setElseExpr(Expression elseExpr) {
+        this.elseExpr = elseExpr;
+    }
+
+    public void setWhenExprs(List<Expression> whenExprs) {
+        this.whenExprs = whenExprs;
+    }
+
+    public void setThenExprs(List<Expression> thenExprs) {
+        this.thenExprs = thenExprs;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("CASE ");
+        sb.append(conditionExpr);
+        sb.append("\n");
+        for (int index = 0; index < whenExprs.size(); ++index) {
+            sb.append("WHEN ");
+            sb.append(whenExprs.get(index));
+            sb.append(" THEN ");
+            sb.append(thenExprs.get(index));
+            sb.append("\n");
+        }
+        sb.append("ELSE ");
+        sb.append(elseExpr);
+        sb.append("END\n");
+        return sb.toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return ObjectUtils.hashCodeMulti(conditionExpr, elseExpr, thenExprs, whenExprs);
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        if (this == object) {
+            return true;
+        }
+        if (!(object instanceof CaseExpression)) {
+            return false;
+        }
+        CaseExpression target = (CaseExpression) object;
+        return ObjectUtils.equals(conditionExpr, target.conditionExpr) && ObjectUtils.equals(elseExpr, target.elseExpr)
+                && ObjectUtils.equals(thenExprs, target.thenExprs) && ObjectUtils.equals(thenExprs, thenExprs);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
index d0e2aa3..c85097d 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
@@ -45,6 +45,7 @@ import org.apache.asterix.lang.sqlpp.clause.SelectElement;
 import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
 import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
 import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
 import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.parser.FunctionParser;
@@ -441,5 +442,18 @@ class SqlppQueryRewriter implements IQueryRewriter {
             return null;
         }
 
+        @Override
+        public Void visit(CaseExpression caseExpression, Void arg) throws AsterixException {
+            caseExpression.getConditionExpr().accept(this, arg);
+            for (Expression expr : caseExpression.getWhenExprs()) {
+                expr.accept(this, arg);
+            }
+            for (Expression expr : caseExpression.getThenExprs()) {
+                expr.accept(this, arg);
+            }
+            caseExpression.getElseExpr().accept(this, arg);
+            return null;
+        }
+
     }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineColumnAliasVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineColumnAliasVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineColumnAliasVisitor.java
index 57cbdc5..4aa25d7 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineColumnAliasVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineColumnAliasVisitor.java
@@ -64,6 +64,7 @@ import org.apache.asterix.lang.sqlpp.clause.SelectElement;
 import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
 import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
 import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
 import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
@@ -462,6 +463,19 @@ public class InlineColumnAliasVisitor extends AbstractSqlppQueryExpressionVisito
         return null;
     }
 
+    @Override
+    public Void visit(CaseExpression caseExpression, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
+        caseExpression.getConditionExpr().accept(this, overwriteWithGbyKeyVarRefs);
+        for (Expression expr : caseExpression.getWhenExprs()) {
+            expr.accept(this, overwriteWithGbyKeyVarRefs);
+        }
+        for (Expression expr : caseExpression.getThenExprs()) {
+            expr.accept(this, overwriteWithGbyKeyVarRefs);
+        }
+        caseExpression.getElseExpr().accept(this, overwriteWithGbyKeyVarRefs);
+        return null;
+    }
+
     private void removeSubsutitions(AbstractBinaryCorrelateClause unnestClause) {
         scopeChecker.getCurrentScope().removeSymbolExpressionMapping(unnestClause.getRightVariable());
         if (unnestClause.hasPositionalVariable()) {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppBuiltinFunctionRewriteVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppBuiltinFunctionRewriteVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppBuiltinFunctionRewriteVisitor.java
index e046ccf..a3346ed 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppBuiltinFunctionRewriteVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppBuiltinFunctionRewriteVisitor.java
@@ -21,13 +21,20 @@ package org.apache.asterix.lang.sqlpp.rewrites.visitor;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.asterix.common.config.MetadataConstants;
 import org.apache.asterix.common.exceptions.AsterixException;
 import org.apache.asterix.common.functions.FunctionSignature;
 import org.apache.asterix.lang.common.base.Expression;
 import org.apache.asterix.lang.common.base.ILangExpression;
 import org.apache.asterix.lang.common.expression.CallExpr;
+import org.apache.asterix.lang.common.expression.LiteralExpr;
+import org.apache.asterix.lang.common.expression.OperatorExpr;
+import org.apache.asterix.lang.common.literal.TrueLiteral;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
 import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
+import org.apache.asterix.lang.sqlpp.util.SqlppRewriteUtil;
 import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppSimpleExpressionVisitor;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 
 public class SqlppBuiltinFunctionRewriteVisitor extends AbstractSqlppSimpleExpressionVisitor {
 
@@ -44,4 +51,49 @@ public class SqlppBuiltinFunctionRewriteVisitor extends AbstractSqlppSimpleExpre
         return callExpr;
     }
 
+    @Override
+    public Expression visit(CaseExpression caseExpr, ILangExpression arg) throws AsterixException {
+        Expression expr = super.visit(caseExpr, arg); // Visits it as usual first.
+        if (expr != caseExpr) {
+            return expr.accept(this, arg);
+        }
+        CaseExpression newCaseExpr = normalizeCaseExpr(caseExpr);
+        if (SqlppRewriteUtil.constainsSubquery(newCaseExpr)) {
+            // If the CASE expression contains a subquery, we do not rewrite it to a switch-case function call.
+            return newCaseExpr;
+        }
+        // If the CASE expression does not contain a subquery, we rewrite it to a switch-case function call.
+        FunctionSignature functionSignature = new FunctionSignature(MetadataConstants.METADATA_DATAVERSE_NAME,
+                "switch-case", FunctionIdentifier.VARARGS);
+        List<Expression> whenExprList = newCaseExpr.getWhenExprs();
+        List<Expression> thenExprList = newCaseExpr.getThenExprs();
+        List<Expression> newExprList = new ArrayList<>();
+        newExprList.add(newCaseExpr.getConditionExpr());
+        for (int index = 0; index < whenExprList.size(); ++index) {
+            newExprList.add(whenExprList.get(index));
+            newExprList.add(thenExprList.get(index));
+        }
+        newExprList.add(newCaseExpr.getElseExpr());
+        return new CallExpr(functionSignature, newExprList);
+    }
+
+    // Normalizes WHEN expressions so that it can have correct NULL/MISSING semantics as well
+    // as type promotion semantics.
+    private CaseExpression normalizeCaseExpr(CaseExpression caseExpr) throws AsterixException {
+        LiteralExpr trueLiteral = new LiteralExpr(TrueLiteral.INSTANCE);
+        Expression conditionExpr = caseExpr.getConditionExpr();
+        if (trueLiteral.equals(conditionExpr)) {
+            return caseExpr;
+        }
+        List<Expression> normalizedWhenExprs = new ArrayList<>();
+        for (Expression expr : caseExpr.getWhenExprs()) {
+            OperatorExpr operatorExpr = new OperatorExpr();
+            operatorExpr.addOperand((Expression) SqlppRewriteUtil.deepCopy(expr));
+            operatorExpr.addOperand(caseExpr.getConditionExpr());
+            operatorExpr.addOperator("=");
+            normalizedWhenExprs.add(operatorExpr);
+        }
+        return new CaseExpression(trueLiteral, normalizedWhenExprs, caseExpr.getThenExprs(), caseExpr.getElseExpr());
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java
index 194c029..d2730ff 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java
@@ -43,6 +43,7 @@ import org.apache.asterix.lang.sqlpp.clause.SelectElement;
 import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
 import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
 import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
 import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
@@ -75,9 +76,7 @@ public class SqlppInlineUdfsVisitor extends AbstractInlineUdfsVisitor
     protected Expression generateQueryExpression(List<LetClause> letClauses, Expression returnExpr)
             throws AsterixException {
         Map<VariableExpr, Expression> varExprMap = extractLetBindingVariableExpressionMappings(letClauses);
-        Expression inlinedReturnExpr = (Expression) SqlppVariableSubstitutionUtil
-                .substituteVariableWithoutContext(returnExpr, varExprMap);
-        return inlinedReturnExpr;
+        return (Expression) SqlppVariableSubstitutionUtil.substituteVariableWithoutContext(returnExpr, varExprMap);
     }
 
     @Override
@@ -231,9 +230,28 @@ public class SqlppInlineUdfsVisitor extends AbstractInlineUdfsVisitor
         return p.first;
     }
 
+    @Override
+    public Boolean visit(CaseExpression caseExpr, List<FunctionDecl> funcs) throws AsterixException {
+        Pair<Boolean, Expression> result = inlineUdfsInExpr(caseExpr.getConditionExpr(), funcs);
+        caseExpr.setConditionExpr(result.second);
+        boolean inlined = result.first;
+
+        Pair<Boolean, List<Expression>> inlinedList = inlineUdfsInExprList(caseExpr.getWhenExprs(), funcs);
+        inlined = inlined || inlinedList.first;
+        caseExpr.setWhenExprs(inlinedList.second);
+
+        inlinedList = inlineUdfsInExprList(caseExpr.getThenExprs(), funcs);
+        inlined = inlined || inlinedList.first;
+        caseExpr.setThenExprs(inlinedList.second);
+
+        result = inlineUdfsInExpr(caseExpr.getElseExpr(), funcs);
+        caseExpr.setElseExpr(result.second);
+        return inlined || result.first;
+    }
+
     private Map<VariableExpr, Expression> extractLetBindingVariableExpressionMappings(List<LetClause> letClauses)
             throws AsterixException {
-        Map<VariableExpr, Expression> varExprMap = new HashMap<VariableExpr, Expression>();
+        Map<VariableExpr, Expression> varExprMap = new HashMap<>();
         for (LetClause lc : letClauses) {
             // inline let variables one by one iteratively.
             lc.setBindingExpr((Expression) SqlppVariableSubstitutionUtil

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppRewriteUtil.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppRewriteUtil.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppRewriteUtil.java
index 4a8c69d..9bc1813 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppRewriteUtil.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppRewriteUtil.java
@@ -28,6 +28,7 @@ import org.apache.asterix.lang.common.base.ILangExpression;
 import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppGroupBySugarVisitor;
+import org.apache.asterix.lang.sqlpp.visitor.CheckSubqueryVisitor;
 import org.apache.asterix.lang.sqlpp.visitor.DeepCopyVisitor;
 import org.apache.asterix.lang.sqlpp.visitor.FreeVariableVisitor;
 
@@ -60,4 +61,13 @@ public class SqlppRewriteUtil {
         return expr.accept(visitor, null);
     }
 
+    // Checks if an ILangExpression contains a subquery.
+    public static boolean constainsSubquery(ILangExpression expr) throws AsterixException {
+        if (expr == null) {
+            return false;
+        }
+        CheckSubqueryVisitor visitor = new CheckSubqueryVisitor();
+        return expr.accept(visitor, null);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java
index 669b0a8..ca25775 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java
@@ -55,13 +55,14 @@ import org.apache.asterix.lang.sqlpp.clause.SelectElement;
 import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
 import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
 import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
 import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
 import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppQueryExpressionVisitor;
 
 /**
- * This visitor checks if a language construct contains SQL-92 aggregates.
+ * This visitor checks if a non-subquery language construct contains SQL-92 aggregates.
  */
 public class CheckSql92AggregateVisitor extends AbstractSqlppQueryExpressionVisitor<Boolean, ILangExpression> {
 
@@ -271,4 +272,10 @@ public class CheckSql92AggregateVisitor extends AbstractSqlppQueryExpressionVisi
         return false;
     }
 
+    @Override
+    public Boolean visit(CaseExpression caseExpr, ILangExpression arg) throws AsterixException {
+        return caseExpr.getConditionExpr().accept(this, arg) || visitExprList(caseExpr.getWhenExprs(), arg)
+                || visitExprList(caseExpr.getThenExprs(), arg) || caseExpr.getElseExpr().accept(this, arg);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSubqueryVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSubqueryVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSubqueryVisitor.java
new file mode 100644
index 0000000..e772df5
--- /dev/null
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSubqueryVisitor.java
@@ -0,0 +1,316 @@
+/*
+ * 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.lang.sqlpp.visitor;
+
+import java.util.List;
+
+import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.lang.common.base.Expression;
+import org.apache.asterix.lang.common.base.ILangExpression;
+import org.apache.asterix.lang.common.clause.GroupbyClause;
+import org.apache.asterix.lang.common.clause.LetClause;
+import org.apache.asterix.lang.common.clause.LimitClause;
+import org.apache.asterix.lang.common.clause.OrderbyClause;
+import org.apache.asterix.lang.common.clause.WhereClause;
+import org.apache.asterix.lang.common.expression.CallExpr;
+import org.apache.asterix.lang.common.expression.FieldAccessor;
+import org.apache.asterix.lang.common.expression.FieldBinding;
+import org.apache.asterix.lang.common.expression.GbyVariableExpressionPair;
+import org.apache.asterix.lang.common.expression.IfExpr;
+import org.apache.asterix.lang.common.expression.IndexAccessor;
+import org.apache.asterix.lang.common.expression.ListConstructor;
+import org.apache.asterix.lang.common.expression.LiteralExpr;
+import org.apache.asterix.lang.common.expression.OperatorExpr;
+import org.apache.asterix.lang.common.expression.QuantifiedExpression;
+import org.apache.asterix.lang.common.expression.RecordConstructor;
+import org.apache.asterix.lang.common.expression.UnaryExpr;
+import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.statement.FunctionDecl;
+import org.apache.asterix.lang.common.statement.Query;
+import org.apache.asterix.lang.common.struct.Identifier;
+import org.apache.asterix.lang.common.struct.QuantifiedPair;
+import org.apache.asterix.lang.sqlpp.clause.AbstractBinaryCorrelateClause;
+import org.apache.asterix.lang.sqlpp.clause.FromClause;
+import org.apache.asterix.lang.sqlpp.clause.FromTerm;
+import org.apache.asterix.lang.sqlpp.clause.HavingClause;
+import org.apache.asterix.lang.sqlpp.clause.JoinClause;
+import org.apache.asterix.lang.sqlpp.clause.NestClause;
+import org.apache.asterix.lang.sqlpp.clause.Projection;
+import org.apache.asterix.lang.sqlpp.clause.SelectBlock;
+import org.apache.asterix.lang.sqlpp.clause.SelectClause;
+import org.apache.asterix.lang.sqlpp.clause.SelectElement;
+import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
+import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
+import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
+import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
+import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
+import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
+import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppQueryExpressionVisitor;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+
+/**
+ * This visitor recursively checks if there is a subquery in the argument language construct.
+ */
+public class CheckSubqueryVisitor extends AbstractSqlppQueryExpressionVisitor<Boolean, ILangExpression> {
+
+    @Override
+    public Boolean visit(FromClause fromClause, ILangExpression arg) throws AsterixException {
+        for (FromTerm fromTerm : fromClause.getFromTerms()) {
+            if (fromTerm.accept(this, arg)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public Boolean visit(FromTerm fromTerm, ILangExpression arg) throws AsterixException {
+        if (visit(fromTerm.getLeftExpression(), arg)) {
+            return true;
+        }
+        for (AbstractBinaryCorrelateClause correlateClause : fromTerm.getCorrelateClauses()) {
+            if (correlateClause.accept(this, arg)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public Boolean visit(JoinClause joinClause, ILangExpression arg) throws AsterixException {
+        return visit(joinClause.getRightExpression(), arg) || visit(joinClause.getConditionExpression(), arg);
+    }
+
+    @Override
+    public Boolean visit(NestClause nestClause, ILangExpression arg) throws AsterixException {
+        return nestClause.accept(this, arg);
+    }
+
+    @Override
+    public Boolean visit(Projection projection, ILangExpression arg) throws AsterixException {
+        if (projection.star()) {
+            return false;
+        }
+        return visit(projection.getExpression(), arg);
+    }
+
+    @Override
+    public Boolean visit(SelectBlock selectBlock, ILangExpression arg) throws AsterixException {
+        boolean hasSubquery = visit(selectBlock.getFromClause(), arg) || visit(selectBlock.getGroupbyClause(), arg)
+                || visit(selectBlock.getHavingClause(), arg) || visit(selectBlock.getWhereClause(), arg);
+        return hasSubquery || visit(selectBlock.getSelectClause(), arg) || visit(selectBlock.getLetList(), arg)
+                || visit(selectBlock.getLetListAfterGroupby(), arg);
+    }
+
+    @Override
+    public Boolean visit(SelectClause selectClause, ILangExpression arg) throws AsterixException {
+        return visit(selectClause.getSelectElement(), arg) || visit(selectClause.getSelectRegular(), arg);
+    }
+
+    @Override
+    public Boolean visit(SelectElement selectElement, ILangExpression arg) throws AsterixException {
+        return visit(selectElement.getExpression(), arg);
+    }
+
+    @Override
+    public Boolean visit(SelectRegular selectRegular, ILangExpression arg) throws AsterixException {
+        return visit(selectRegular.getProjections(), arg);
+    }
+
+    @Override
+    public Boolean visit(SelectSetOperation selectSetOperation, ILangExpression arg) throws AsterixException {
+        if (selectSetOperation.getLeftInput().accept(this, arg)) {
+            return true;
+        }
+        for (SetOperationRight right : selectSetOperation.getRightInputs()) {
+            if (right.getSetOperationRightInput().accept(this, arg)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public Boolean visit(SelectExpression selectStatement, ILangExpression arg) throws AsterixException {
+        if (selectStatement.isSubquery()) {
+            return true;
+        }
+        return visit(selectStatement.getLetList(), arg) || visit(selectStatement.getSelectSetOperation(), arg)
+                || visit(selectStatement.getOrderbyClause(), arg) || visit(selectStatement.getLimitClause(), arg);
+
+    }
+
+    @Override
+    public Boolean visit(UnnestClause unnestClause, ILangExpression arg) throws AsterixException {
+        return visit(unnestClause.getRightExpression(), arg);
+    }
+
+    @Override
+    public Boolean visit(HavingClause havingClause, ILangExpression arg) throws AsterixException {
+        return visit(havingClause.getFilterExpression(), arg);
+    }
+
+    @Override
+    public Boolean visit(IndependentSubquery independentSubquery, ILangExpression arg) throws AsterixException {
+        return visit(independentSubquery.getExpr(), arg);
+    }
+
+    @Override
+    public Boolean visit(CaseExpression caseExpression, ILangExpression arg) throws AsterixException {
+        return visit(caseExpression.getConditionExpr(), arg) || visit(caseExpression.getWhenExprs(), arg)
+                || visit(caseExpression.getThenExprs(), arg) || visit(caseExpression.getElseExpr(), arg);
+    }
+
+    @Override
+    public Boolean visit(Query q, ILangExpression arg) throws AsterixException {
+        return visit(q.getBody(), arg);
+    }
+
+    @Override
+    public Boolean visit(FunctionDecl fd, ILangExpression arg) throws AsterixException {
+        return fd.getFuncBody().accept(this, arg);
+    }
+
+    @Override
+    public Boolean visit(LiteralExpr l, ILangExpression arg) throws AsterixException {
+        return false;
+    }
+
+    @Override
+    public Boolean visit(VariableExpr v, ILangExpression arg) throws AsterixException {
+        return false;
+    }
+
+    @Override
+    public Boolean visit(ListConstructor lc, ILangExpression arg) throws AsterixException {
+        return visit(lc.getExprList(), arg);
+    }
+
+    @Override
+    public Boolean visit(RecordConstructor rc, ILangExpression arg) throws AsterixException {
+        for (FieldBinding fb : rc.getFbList()) {
+            if (visit(fb.getLeftExpr(), arg)) {
+                return true;
+            }
+            if (visit(fb.getRightExpr(), arg)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public Boolean visit(OperatorExpr operatorExpr, ILangExpression arg) throws AsterixException {
+        return visit(operatorExpr.getExprList(), arg);
+    }
+
+    @Override
+    public Boolean visit(FieldAccessor fa, ILangExpression arg) throws AsterixException {
+        return visit(fa.getExpr(), arg);
+    }
+
+    @Override
+    public Boolean visit(IndexAccessor ia, ILangExpression arg) throws AsterixException {
+        return visit(ia.getExpr(), arg) || visit(ia.getIndexExpr(), arg);
+    }
+
+    @Override
+    public Boolean visit(IfExpr ifexpr, ILangExpression arg) throws AsterixException {
+        return visit(ifexpr.getCondExpr(), arg) || visit(ifexpr.getThenExpr(), arg) || visit(ifexpr.getElseExpr(), arg);
+    }
+
+    @Override
+    public Boolean visit(QuantifiedExpression qe, ILangExpression arg) throws AsterixException {
+        for (QuantifiedPair qf : qe.getQuantifiedList()) {
+            if (visit(qf.getExpr(), arg)) {
+                return true;
+            }
+        }
+        return visit(qe.getSatisfiesExpr(), arg);
+    }
+
+    @Override
+    public Boolean visit(LetClause lc, ILangExpression arg) throws AsterixException {
+        return visit(lc.getBindingExpr(), arg);
+    }
+
+    @Override
+    public Boolean visit(WhereClause wc, ILangExpression arg) throws AsterixException {
+        return visit(wc.getWhereExpr(), arg);
+    }
+
+    @Override
+    public Boolean visit(OrderbyClause oc, ILangExpression arg) throws AsterixException {
+        return visit(oc.getOrderbyList(), arg);
+    }
+
+    @Override
+    public Boolean visit(GroupbyClause gc, ILangExpression arg) throws AsterixException {
+        for (GbyVariableExpressionPair key : gc.getGbyPairList()) {
+            if (visit(key.getExpr(), arg)) {
+                return true;
+            }
+        }
+        for (GbyVariableExpressionPair key : gc.getDecorPairList()) {
+            if (visit(key.getExpr(), arg)) {
+                return true;
+            }
+        }
+        for (Pair<Expression, Identifier> field : gc.getGroupFieldList()) {
+            if (visit(field.first, arg)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public Boolean visit(LimitClause lc, ILangExpression arg) throws AsterixException {
+        return visit(lc.getLimitExpr(), arg) || visit(lc.getOffset(), arg);
+    }
+
+    @Override
+    public Boolean visit(UnaryExpr u, ILangExpression arg) throws AsterixException {
+        return visit(u.getExpr(), arg);
+    }
+
+    @Override
+    public Boolean visit(CallExpr callExpr, ILangExpression arg) throws AsterixException {
+        return visit(callExpr.getExprList(), arg);
+    }
+
+    private boolean visit(List<?> langExprs, ILangExpression arg) throws AsterixException {
+        for (Object o : langExprs) {
+            ILangExpression langExpr = (ILangExpression) o;
+            if (langExpr.accept(this, arg)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean visit(ILangExpression langExpr, ILangExpression arg) throws AsterixException {
+        if (langExpr == null) {
+            return false;
+        }
+        return langExpr.accept(this, arg);
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
index bafb8c0..01f3524 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
@@ -60,6 +60,7 @@ import org.apache.asterix.lang.sqlpp.clause.SelectElement;
 import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
 import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
 import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
 import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationInput;
@@ -334,11 +335,7 @@ public class DeepCopyVisitor extends AbstractSqlppQueryExpressionVisitor<ILangEx
 
     @Override
     public ListConstructor visit(ListConstructor lc, Void arg) throws AsterixException {
-        List<Expression> newExprList = new ArrayList<>();
-        for (Expression expr : lc.getExprList()) {
-            newExprList.add((Expression) expr.accept(this, arg));
-        }
-        return new ListConstructor(lc.getType(), newExprList);
+        return new ListConstructor(lc.getType(), copyExprList(lc.getExprList(), arg));
     }
 
     @Override
@@ -354,12 +351,8 @@ public class DeepCopyVisitor extends AbstractSqlppQueryExpressionVisitor<ILangEx
 
     @Override
     public OperatorExpr visit(OperatorExpr operatorExpr, Void arg) throws AsterixException {
-        List<Expression> newExprList = new ArrayList<>();
-        for (Expression expr : operatorExpr.getExprList()) {
-            newExprList.add((Expression) expr.accept(this, arg));
-        }
-        return new OperatorExpr(newExprList, operatorExpr.getExprBroadcastIdx(), operatorExpr.getOpList(),
-                operatorExpr.isCurrentop());
+        return new OperatorExpr(copyExprList(operatorExpr.getExprList(), arg), operatorExpr.getExprBroadcastIdx(),
+                operatorExpr.getOpList(), operatorExpr.isCurrentop());
     }
 
     @Override
@@ -415,7 +408,7 @@ public class DeepCopyVisitor extends AbstractSqlppQueryExpressionVisitor<ILangEx
         Expression expr = (Expression) ia.getExpr().accept(this, arg);
         Expression indexExpr = null;
         if (ia.getIndexExpr() != null) {
-            indexExpr = ia.getIndexExpr();
+            indexExpr = (Expression) ia.getIndexExpr().accept(this, arg);
         }
         return new IndexAccessor(expr, indexExpr);
     }
@@ -425,4 +418,21 @@ public class DeepCopyVisitor extends AbstractSqlppQueryExpressionVisitor<ILangEx
         return new IndependentSubquery((Expression) independentSubquery.getExpr().accept(this, arg));
     }
 
+    @Override
+    public ILangExpression visit(CaseExpression caseExpr, Void arg) throws AsterixException {
+        Expression conditionExpr = (Expression) caseExpr.getConditionExpr().accept(this, arg);
+        List<Expression> whenExprList = copyExprList(caseExpr.getWhenExprs(), arg);
+        List<Expression> thenExprList = copyExprList(caseExpr.getThenExprs(), arg);
+        Expression elseExpr = (Expression) caseExpr.getElseExpr().accept(this, arg);
+        return new CaseExpression(conditionExpr, whenExprList, thenExprList, elseExpr);
+    }
+
+    private List<Expression> copyExprList(List<Expression> exprs, Void arg) throws AsterixException {
+        List<Expression> newExprList = new ArrayList<>();
+        for (Expression expr : exprs) {
+            newExprList.add((Expression) expr.accept(this, arg));
+        }
+        return newExprList;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
index 37c19ab..20b144c 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
@@ -60,6 +60,7 @@ import org.apache.asterix.lang.sqlpp.clause.SelectElement;
 import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
 import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
 import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
 import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
@@ -159,8 +160,8 @@ public class FreeVariableVisitor extends AbstractSqlppQueryExpressionVisitor<Voi
         Collection<VariableExpr> fromBindingVars = SqlppVariableUtil.getBindingVariables(selectBlock.getFromClause());
         Collection<VariableExpr> letsBindingVars = SqlppVariableUtil.getBindingVariables(selectBlock.getLetList());
         Collection<VariableExpr> gbyBindingVars = SqlppVariableUtil.getBindingVariables(selectBlock.getGroupbyClause());
-        Collection<VariableExpr> gbyLetsBindingVars = SqlppVariableUtil
-                .getBindingVariables(selectBlock.getLetListAfterGroupby());
+        Collection<VariableExpr> gbyLetsBindingVars =
+                SqlppVariableUtil.getBindingVariables(selectBlock.getLetListAfterGroupby());
 
         selectBlock.getSelectClause().accept(this, selectFreeVars);
         // Removes group-by, from, let, and gby-let binding vars.
@@ -270,9 +271,7 @@ public class FreeVariableVisitor extends AbstractSqlppQueryExpressionVisitor<Voi
 
     @Override
     public Void visit(OrderbyClause oc, Collection<VariableExpr> freeVars) throws AsterixException {
-        for (Expression orderExpr : oc.getOrderbyList()) {
-            orderExpr.accept(this, freeVars);
-        }
+        visit(oc.getOrderbyList(), freeVars);
         return null;
     }
 
@@ -340,9 +339,7 @@ public class FreeVariableVisitor extends AbstractSqlppQueryExpressionVisitor<Voi
 
     @Override
     public Void visit(ListConstructor lc, Collection<VariableExpr> freeVars) throws AsterixException {
-        for (Expression expr : lc.getExprList()) {
-            expr.accept(this, freeVars);
-        }
+        visit(lc.getExprList(), freeVars);
         return null;
     }
 
@@ -357,9 +354,7 @@ public class FreeVariableVisitor extends AbstractSqlppQueryExpressionVisitor<Voi
 
     @Override
     public Void visit(OperatorExpr operatorExpr, Collection<VariableExpr> freeVars) throws AsterixException {
-        for (Expression expr : operatorExpr.getExprList()) {
-            expr.accept(this, freeVars);
-        }
+        visit(operatorExpr.getExprList(), freeVars);
         return null;
     }
 
@@ -416,8 +411,18 @@ public class FreeVariableVisitor extends AbstractSqlppQueryExpressionVisitor<Voi
     }
 
     @Override
-    public Void visit(IndependentSubquery independentSubquery, Collection<VariableExpr> arg) throws AsterixException {
-        independentSubquery.getExpr().accept(this, arg);
+    public Void visit(IndependentSubquery independentSubquery, Collection<VariableExpr> freeVars)
+            throws AsterixException {
+        independentSubquery.getExpr().accept(this, freeVars);
+        return null;
+    }
+
+    @Override
+    public Void visit(CaseExpression caseExpr, Collection<VariableExpr> freeVars) throws AsterixException {
+        caseExpr.getConditionExpr().accept(this, freeVars);
+        visit(caseExpr.getWhenExprs(), freeVars);
+        visit(caseExpr.getThenExprs(), freeVars);
+        caseExpr.getElseExpr().accept(this, freeVars);
         return null;
     }
 
@@ -454,6 +459,12 @@ public class FreeVariableVisitor extends AbstractSqlppQueryExpressionVisitor<Voi
         freeVars.addAll(conditionFreeVars);
     }
 
+    private void visit(List<Expression> exprs, Collection<VariableExpr> arg) throws AsterixException {
+        for (Expression expr : exprs) {
+            expr.accept(this, arg);
+        }
+    }
+
     /**
      * Removes all binding variables defined in the select block for a free variable collection.
      *

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java
index 589381a..4413961 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java
@@ -19,6 +19,7 @@
 package org.apache.asterix.lang.sqlpp.visitor;
 
 import java.io.PrintWriter;
+import java.util.List;
 
 import org.apache.asterix.common.exceptions.AsterixException;
 import org.apache.asterix.common.functions.FunctionSignature;
@@ -42,6 +43,7 @@ import org.apache.asterix.lang.sqlpp.clause.SelectElement;
 import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
 import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
 import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
 import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
@@ -250,8 +252,8 @@ public class SqlppAstPrintVisitor extends QueryPrintVisitor implements ISqlppVis
     @Override
     public Void visit(CallExpr pf, Integer step) throws AsterixException {
         FunctionSignature functionSignature = pf.getFunctionSignature();
-        FunctionSignature normalizedFunctionSignature = FunctionMapUtil
-                .normalizeBuiltinFunctionSignature(functionSignature, false);
+        FunctionSignature normalizedFunctionSignature =
+                FunctionMapUtil.normalizeBuiltinFunctionSignature(functionSignature, false);
         if (AsterixBuiltinFunctions.isBuiltinCompilerFunction(normalizedFunctionSignature, true)) {
             functionSignature = normalizedFunctionSignature;
         }
@@ -299,4 +301,25 @@ public class SqlppAstPrintVisitor extends QueryPrintVisitor implements ISqlppVis
         return null;
     }
 
+    @Override
+    public Void visit(CaseExpression caseExpr, Integer step) throws AsterixException {
+        out.print(skip(step) + "CASE");
+        caseExpr.getConditionExpr().accept(this, step + 2);
+        out.println();
+        List<Expression> whenExprs = caseExpr.getWhenExprs();
+        List<Expression> thenExprs = caseExpr.getThenExprs();
+        for (int index = 0; index < whenExprs.size(); ++index) {
+            out.print(skip(step) + "WHEN ");
+            whenExprs.get(index).accept(this, step + 2);
+            out.print(skip(step) + "THEN ");
+            thenExprs.get(index).accept(this, step + 2);
+            out.println();
+        }
+        out.print(skip(step) + "ELSE ");
+        caseExpr.getElseExpr().accept(this, step + 2);
+        out.println();
+        out.println(skip(step) + "END");
+        return null;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppCloneAndSubstituteVariablesVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppCloneAndSubstituteVariablesVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppCloneAndSubstituteVariablesVisitor.java
index d380cad..23181e4 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppCloneAndSubstituteVariablesVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppCloneAndSubstituteVariablesVisitor.java
@@ -33,6 +33,7 @@ import org.apache.asterix.lang.common.clause.WhereClause;
 import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.common.rewrites.VariableSubstitutionEnvironment;
+import org.apache.asterix.lang.common.util.VariableCloneAndSubstitutionUtil;
 import org.apache.asterix.lang.common.visitor.CloneAndSubstituteVariablesVisitor;
 import org.apache.asterix.lang.sqlpp.clause.AbstractBinaryCorrelateClause;
 import org.apache.asterix.lang.sqlpp.clause.FromClause;
@@ -47,6 +48,7 @@ import org.apache.asterix.lang.sqlpp.clause.SelectElement;
 import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
 import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
 import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
 import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationInput;
@@ -377,4 +379,17 @@ public class SqlppCloneAndSubstituteVariablesVisitor extends CloneAndSubstituteV
         return new Pair<>(newSubquery, p.second);
     }
 
+    @Override
+    public Pair<ILangExpression, VariableSubstitutionEnvironment> visit(CaseExpression caseExpr,
+            VariableSubstitutionEnvironment env) throws AsterixException {
+        Expression conditionExpr = (Expression) caseExpr.getConditionExpr().accept(this, env).first;
+        List<Expression> whenExprList =
+                VariableCloneAndSubstitutionUtil.visitAndCloneExprList(caseExpr.getWhenExprs(), env, this);
+        List<Expression> thenExprList =
+                VariableCloneAndSubstitutionUtil.visitAndCloneExprList(caseExpr.getThenExprs(), env, this);
+        Expression elseExpr = (Expression) caseExpr.getElseExpr().accept(this, env).first;
+        CaseExpression newCaseExpr = new CaseExpression(conditionExpr, whenExprList, thenExprList, elseExpr);
+        return new Pair<>(newCaseExpr, env);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppFormatPrintVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppFormatPrintVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppFormatPrintVisitor.java
index 2dca532..0363e20 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppFormatPrintVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppFormatPrintVisitor.java
@@ -41,6 +41,7 @@ import org.apache.asterix.lang.sqlpp.clause.SelectElement;
 import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
 import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
 import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
 import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
@@ -307,4 +308,25 @@ public class SqlppFormatPrintVisitor extends FormatPrintVisitor implements ISqlp
         return null;
     }
 
+    @Override
+    public Void visit(CaseExpression caseExpr, Integer step) throws AsterixException {
+        out.print(skip(step) + "case ");
+        caseExpr.getConditionExpr().accept(this, step + 2);
+        out.println();
+        List<Expression> whenExprs = caseExpr.getWhenExprs();
+        List<Expression> thenExprs = caseExpr.getThenExprs();
+        for (int index = 0; index < whenExprs.size(); ++index) {
+            out.print(skip(step) + "when ");
+            whenExprs.get(index).accept(this, step + 2);
+            out.print(" then ");
+            thenExprs.get(index).accept(this, step + 2);
+            out.println();
+        }
+        out.print(skip(step) + "else ");
+        caseExpr.getElseExpr().accept(this, step + 2);
+        out.println();
+        out.println(skip(step) + "end");
+        return null;
+    }
+
 }


[3/4] asterixdb git commit: Support CASE expression in SQL++.

Posted by bu...@apache.org.
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryInvertedIndexOperationsHelper.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryInvertedIndexOperationsHelper.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryInvertedIndexOperationsHelper.java
index 7044205..c2d2f7c 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryInvertedIndexOperationsHelper.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryInvertedIndexOperationsHelper.java
@@ -113,8 +113,8 @@ public class SecondaryInvertedIndexOperationsHelper extends SecondaryIndexOperat
         // Prepare record descriptor used in the assign op, and the optional
         // select op.
         secondaryFieldAccessEvalFactories = new IScalarEvaluatorFactory[numSecondaryKeys + numFilterFields];
-        ISerializerDeserializer[] secondaryRecFields = new ISerializerDeserializer[numPrimaryKeys + numSecondaryKeys
-                + numFilterFields];
+        ISerializerDeserializer[] secondaryRecFields =
+                new ISerializerDeserializer[numPrimaryKeys + numSecondaryKeys + numFilterFields];
         ISerializerDeserializer[] enforcedRecFields = new ISerializerDeserializer[1 + numPrimaryKeys + numFilterFields];
         secondaryTypeTraits = new ITypeTraits[numSecondaryKeys + numPrimaryKeys];
         ITypeTraits[] enforcedTypeTraits = new ITypeTraits[1 + numPrimaryKeys];
@@ -123,8 +123,8 @@ public class SecondaryInvertedIndexOperationsHelper extends SecondaryIndexOperat
         if (numSecondaryKeys > 0) {
             secondaryFieldAccessEvalFactories[0] = FormatUtils.getDefaultFormat().getFieldAccessEvaluatorFactory(
                     isEnforcingKeyTypes ? enforcedItemType : itemType, secondaryKeyFields.get(0), numPrimaryKeys);
-            Pair<IAType, Boolean> keyTypePair = Index.getNonNullableOpenFieldType(secondaryKeyTypes.get(0),
-                    secondaryKeyFields.get(0), itemType);
+            Pair<IAType, Boolean> keyTypePair =
+                    Index.getNonNullableOpenFieldType(secondaryKeyTypes.get(0), secondaryKeyFields.get(0), itemType);
             secondaryKeyType = keyTypePair.first;
             anySecondaryKeyIsNullable = anySecondaryKeyIsNullable || keyTypePair.second;
             ISerializerDeserializer keySerde = serdeProvider.getSerializerDeserializer(secondaryKeyType);
@@ -154,8 +154,8 @@ public class SecondaryInvertedIndexOperationsHelper extends SecondaryIndexOperat
         // Set tokenizer factory.
         // TODO: We might want to expose the hashing option at the AQL level,
         // and add the choice to the index metadata.
-        tokenizerFactory = NonTaggedFormatUtil.getBinaryTokenizerFactory(secondaryKeyType.getTypeTag(), indexType,
-                gramLength);
+        tokenizerFactory =
+                NonTaggedFormatUtil.getBinaryTokenizerFactory(secondaryKeyType.getTypeTag(), indexType, gramLength);
         // Type traits for inverted-list elements. Inverted lists contain
         // primary keys.
         invListsTypeTraits = new ITypeTraits[numPrimaryKeys];
@@ -169,8 +169,8 @@ public class SecondaryInvertedIndexOperationsHelper extends SecondaryIndexOperat
         // For tokenization, sorting and loading.
         // One token (+ optional partitioning field) + primary keys.
         numTokenKeyPairFields = (!isPartitioned) ? 1 + numPrimaryKeys : 2 + numPrimaryKeys;
-        ISerializerDeserializer[] tokenKeyPairFields = new ISerializerDeserializer[numTokenKeyPairFields
-                + numFilterFields];
+        ISerializerDeserializer[] tokenKeyPairFields =
+                new ISerializerDeserializer[numTokenKeyPairFields + numFilterFields];
         ITypeTraits[] tokenKeyPairTypeTraits = new ITypeTraits[numTokenKeyPairFields];
         tokenKeyPairComparatorFactories = new IBinaryComparatorFactory[numTokenKeyPairFields];
         tokenKeyPairFields[0] = serdeProvider.getSerializerDeserializer(secondaryKeyType);
@@ -226,11 +226,11 @@ public class SecondaryInvertedIndexOperationsHelper extends SecondaryIndexOperat
                 localResourceMetadata, LocalResource.LSMInvertedIndexResource);
 
         IIndexDataflowHelperFactory dataflowHelperFactory = createDataflowHelperFactory();
-        LSMInvertedIndexCreateOperatorDescriptor invIndexCreateOp = new LSMInvertedIndexCreateOperatorDescriptor(spec,
-                AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER, secondaryFileSplitProvider,
-                AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER, tokenTypeTraits, tokenComparatorFactories,
-                invListsTypeTraits, primaryComparatorFactories, tokenizerFactory, dataflowHelperFactory,
-                localResourceFactoryProvider, NoOpOperationCallbackFactory.INSTANCE);
+        LSMInvertedIndexCreateOperatorDescriptor invIndexCreateOp =
+                new LSMInvertedIndexCreateOperatorDescriptor(spec, AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER,
+                        secondaryFileSplitProvider, AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER, tokenTypeTraits,
+                        tokenComparatorFactories, invListsTypeTraits, primaryComparatorFactories, tokenizerFactory,
+                        dataflowHelperFactory, localResourceFactoryProvider, NoOpOperationCallbackFactory.INSTANCE);
         AlgebricksPartitionConstraintHelper.setPartitionConstraintInJobSpec(spec, invIndexCreateOp,
                 secondaryPartitionConstraint);
         spec.addRoot(invIndexCreateOp);
@@ -249,12 +249,12 @@ public class SecondaryInvertedIndexOperationsHelper extends SecondaryIndexOperat
         BTreeSearchOperatorDescriptor primaryScanOp = createPrimaryIndexScanOp(spec);
 
         AbstractOperatorDescriptor sourceOp = primaryScanOp;
-        if (isEnforcingKeyTypes) {
+        if (isEnforcingKeyTypes && !enforcedItemType.equals(itemType)) {
             sourceOp = createCastOp(spec, dataset.getDatasetType());
             spec.connect(new OneToOneConnectorDescriptor(spec), primaryScanOp, 0, sourceOp, 0);
         }
-        AlgebricksMetaOperatorDescriptor asterixAssignOp = createAssignOp(spec, sourceOp, numSecondaryKeys,
-                secondaryRecDesc);
+        AlgebricksMetaOperatorDescriptor asterixAssignOp =
+                createAssignOp(spec, sourceOp, numSecondaryKeys, secondaryRecDesc);
 
         // If any of the secondary fields are nullable, then add a select op
         // that filters nulls.
@@ -267,8 +267,8 @@ public class SecondaryInvertedIndexOperationsHelper extends SecondaryIndexOperat
         AbstractOperatorDescriptor tokenizerOp = createTokenizerOp(spec);
 
         // Sort by token + primary keys.
-        ExternalSortOperatorDescriptor sortOp = createSortOp(spec, tokenKeyPairComparatorFactories,
-                tokenKeyPairRecDesc);
+        ExternalSortOperatorDescriptor sortOp =
+                createSortOp(spec, tokenKeyPairComparatorFactories, tokenKeyPairRecDesc);
 
         // Create secondary inverted index bulk load op.
         LSMInvertedIndexBulkLoadOperatorDescriptor invIndexBulkLoadOp = createInvertedIndexBulkLoadOp(spec);
@@ -364,11 +364,11 @@ public class SecondaryInvertedIndexOperationsHelper extends SecondaryIndexOperat
         JobSpecification spec = JobSpecificationUtils.createJobSpecification();
 
         IIndexDataflowHelperFactory dataflowHelperFactory = createDataflowHelperFactory();
-        LSMInvertedIndexCompactOperator compactOp = new LSMInvertedIndexCompactOperator(spec,
-                AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER, secondaryFileSplitProvider,
-                AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER, tokenTypeTraits, tokenComparatorFactories,
-                invListsTypeTraits, primaryComparatorFactories, tokenizerFactory, dataflowHelperFactory,
-                NoOpOperationCallbackFactory.INSTANCE);
+        LSMInvertedIndexCompactOperator compactOp =
+                new LSMInvertedIndexCompactOperator(spec, AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER,
+                        secondaryFileSplitProvider, AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER, tokenTypeTraits,
+                        tokenComparatorFactories, invListsTypeTraits, primaryComparatorFactories, tokenizerFactory,
+                        dataflowHelperFactory, NoOpOperationCallbackFactory.INSTANCE);
         AlgebricksPartitionConstraintHelper.setPartitionConstraintInJobSpec(spec, compactOp,
                 secondaryPartitionConstraint);
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryRTreeOperationsHelper.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryRTreeOperationsHelper.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryRTreeOperationsHelper.java
index 7c500cf..cc9675d 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryRTreeOperationsHelper.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryRTreeOperationsHelper.java
@@ -112,8 +112,8 @@ public class SecondaryRTreeOperationsHelper extends SecondaryIndexOperationsHelp
                     AqlMetadataProvider.proposeLinearizer(keyType, secondaryComparatorFactories.length),
                     dataset.getDatasetId(), mergePolicyFactory, mergePolicyFactoryProperties, filterTypeTraits,
                     filterCmpFactories, rtreeFields, primaryKeyFields, secondaryFilterFields, isPointMBR);
-            localResourceFactoryProvider = new PersistentLocalResourceFactoryProvider(localResourceMetadata,
-                    LocalResource.LSMRTreeResource);
+            localResourceFactoryProvider =
+                    new PersistentLocalResourceFactoryProvider(localResourceMetadata, LocalResource.LSMRTreeResource);
             indexDataflowHelperFactory = new LSMRTreeWithAntiMatterTuplesDataflowHelperFactory(valueProviderFactories,
                     RTreePolicyType.RTREE, btreeCompFactories,
                     new AsterixVirtualBufferCacheProvider(dataset.getDatasetId()), mergePolicyFactory,
@@ -181,8 +181,8 @@ public class SecondaryRTreeOperationsHelper extends SecondaryIndexOperationsHelp
             throw new AsterixException("Cannot use " + numSecondaryKeys
                     + " fields as a key for the R-tree index. There can be only one field as a key for the R-tree index.");
         }
-        Pair<IAType, Boolean> spatialTypePair = Index.getNonNullableOpenFieldType(secondaryKeyTypes.get(0),
-                secondaryKeyFields.get(0), itemType);
+        Pair<IAType, Boolean> spatialTypePair =
+                Index.getNonNullableOpenFieldType(secondaryKeyTypes.get(0), secondaryKeyFields.get(0), itemType);
         IAType spatialType = spatialTypePair.first;
         anySecondaryKeyIsNullable = spatialTypePair.second;
         if (spatialType == null) {
@@ -192,24 +192,24 @@ public class SecondaryRTreeOperationsHelper extends SecondaryIndexOperationsHelp
         int numDimensions = NonTaggedFormatUtil.getNumDimensions(spatialType.getTypeTag());
         numNestedSecondaryKeyFields = numDimensions * 2;
         int recordColumn = dataset.getDatasetType() == DatasetType.INTERNAL ? numPrimaryKeys : 0;
-        secondaryFieldAccessEvalFactories = metadata.getFormat().createMBRFactory(
-                isEnforcingKeyTypes ? enforcedItemType : itemType, secondaryKeyFields.get(0), recordColumn,
-                numDimensions, filterFieldName);
+        secondaryFieldAccessEvalFactories =
+                metadata.getFormat().createMBRFactory(isEnforcingKeyTypes ? enforcedItemType : itemType,
+                        secondaryKeyFields.get(0), recordColumn, numDimensions, filterFieldName);
         secondaryComparatorFactories = new IBinaryComparatorFactory[numNestedSecondaryKeyFields];
         valueProviderFactories = new IPrimitiveValueProviderFactory[numNestedSecondaryKeyFields];
-        ISerializerDeserializer[] secondaryRecFields = new ISerializerDeserializer[numPrimaryKeys
-                + numNestedSecondaryKeyFields + numFilterFields];
+        ISerializerDeserializer[] secondaryRecFields =
+                new ISerializerDeserializer[numPrimaryKeys + numNestedSecondaryKeyFields + numFilterFields];
         ISerializerDeserializer[] enforcedRecFields = new ISerializerDeserializer[1 + numPrimaryKeys + numFilterFields];
         secondaryTypeTraits = new ITypeTraits[numNestedSecondaryKeyFields + numPrimaryKeys];
         ITypeTraits[] enforcedTypeTraits = new ITypeTraits[1 + numPrimaryKeys];
         IAType nestedKeyType = NonTaggedFormatUtil.getNestedSpatialType(spatialType.getTypeTag());
         keyType = nestedKeyType.getTypeTag();
         for (int i = 0; i < numNestedSecondaryKeyFields; i++) {
-            ISerializerDeserializer keySerde = AqlSerializerDeserializerProvider.INSTANCE
-                    .getSerializerDeserializer(nestedKeyType);
+            ISerializerDeserializer keySerde =
+                    AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(nestedKeyType);
             secondaryRecFields[i] = keySerde;
-            secondaryComparatorFactories[i] = AqlBinaryComparatorFactoryProvider.INSTANCE
-                    .getBinaryComparatorFactory(nestedKeyType, true);
+            secondaryComparatorFactories[i] =
+                    AqlBinaryComparatorFactoryProvider.INSTANCE.getBinaryComparatorFactory(nestedKeyType, true);
             secondaryTypeTraits[i] = AqlTypeTraitProvider.INSTANCE.getTypeTrait(nestedKeyType);
             valueProviderFactories[i] = AqlPrimitiveValueProviderFactory.INSTANCE;
 
@@ -230,8 +230,8 @@ public class SecondaryRTreeOperationsHelper extends SecondaryIndexOperationsHelp
                 enforcedTypeTraits[i] = IndexingConstants.getTypeTraits(i);
             }
         }
-        enforcedRecFields[numPrimaryKeys] = AqlSerializerDeserializerProvider.INSTANCE
-                .getSerializerDeserializer(itemType);
+        enforcedRecFields[numPrimaryKeys] =
+                AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(itemType);
         enforcedRecDesc = new RecordDescriptor(enforcedRecFields, enforcedTypeTraits);
         if (numFilterFields > 0) {
             rtreeFields = new int[numNestedSecondaryKeyFields + numPrimaryKeys];
@@ -282,10 +282,10 @@ public class SecondaryRTreeOperationsHelper extends SecondaryIndexOperationsHelp
         JobSpecification spec = JobSpecificationUtils.createJobSpecification();
         boolean temp = dataset.getDatasetDetails().isTemp();
         int[] fieldPermutation = createFieldPermutationForBulkLoadOp(numNestedSecondaryKeyFields);
-        int numNestedSecondaryKeFieldsConsideringPointMBR = isPointMBR ? numNestedSecondaryKeyFields / 2
-                : numNestedSecondaryKeyFields;
-        RecordDescriptor secondaryRecDescConsideringPointMBR = isPointMBR ? secondaryRecDescForPointMBR
-                : secondaryRecDesc;
+        int numNestedSecondaryKeFieldsConsideringPointMBR =
+                isPointMBR ? numNestedSecondaryKeyFields / 2 : numNestedSecondaryKeyFields;
+        RecordDescriptor secondaryRecDescConsideringPointMBR =
+                isPointMBR ? secondaryRecDescForPointMBR : secondaryRecDesc;
         if (dataset.getDatasetType() == DatasetType.INTERNAL) {
             // Create dummy key provider for feeding the primary index scan.
             AbstractOperatorDescriptor keyProviderOp = createDummyKeyProviderOp(spec);
@@ -295,7 +295,7 @@ public class SecondaryRTreeOperationsHelper extends SecondaryIndexOperationsHelp
 
             // Assign op.
             AbstractOperatorDescriptor sourceOp = primaryScanOp;
-            if (isEnforcingKeyTypes) {
+            if (isEnforcingKeyTypes && !enforcedItemType.equals(itemType)) {
                 sourceOp = createCastOp(spec, dataset.getDatasetType());
                 spec.connect(new OneToOneConnectorDescriptor(spec), primaryScanOp, 0, sourceOp, 0);
             }
@@ -310,10 +310,11 @@ public class SecondaryRTreeOperationsHelper extends SecondaryIndexOperationsHelp
             }
 
             // Sort by secondary keys.
-            ExternalSortOperatorDescriptor sortOp = createSortOp(spec,
-                    new IBinaryComparatorFactory[] {
-                            AqlMetadataProvider.proposeLinearizer(keyType, secondaryComparatorFactories.length) },
-                    isPointMBR ? secondaryRecDescForPointMBR : secondaryRecDesc);
+            ExternalSortOperatorDescriptor sortOp =
+                    createSortOp(spec,
+                            new IBinaryComparatorFactory[] { AqlMetadataProvider.proposeLinearizer(keyType,
+                                    secondaryComparatorFactories.length) },
+                            isPointMBR ? secondaryRecDescForPointMBR : secondaryRecDesc);
 
             AsterixStorageProperties storageProperties = propertiesProvider.getStorageProperties();
 
@@ -327,8 +328,8 @@ public class SecondaryRTreeOperationsHelper extends SecondaryIndexOperationsHelp
                     filterTypeTraits, filterCmpFactories, secondaryFilterFields, !temp, isPointMBR);;
 
             // Create secondary RTree bulk load op.
-            TreeIndexBulkLoadOperatorDescriptor secondaryBulkLoadOp = createTreeIndexBulkLoadOp(spec, fieldPermutation,
-                    idff, GlobalConfig.DEFAULT_TREE_FILL_FACTOR);
+            TreeIndexBulkLoadOperatorDescriptor secondaryBulkLoadOp =
+                    createTreeIndexBulkLoadOp(spec, fieldPermutation, idff, GlobalConfig.DEFAULT_TREE_FILL_FACTOR);
             AlgebricksMetaOperatorDescriptor metaOp = new AlgebricksMetaOperatorDescriptor(spec, 1, 0,
                     new IPushRuntimeFactory[] { new SinkRuntimeFactory() }, new RecordDescriptor[] {});
             // Connect the operators.
@@ -353,7 +354,7 @@ public class SecondaryRTreeOperationsHelper extends SecondaryIndexOperationsHelp
             // Create external indexing scan operator
             ExternalDataScanOperatorDescriptor primaryScanOp = createExternalIndexingOp(spec);
             AbstractOperatorDescriptor sourceOp = primaryScanOp;
-            if (isEnforcingKeyTypes) {
+            if (isEnforcingKeyTypes && !enforcedItemType.equals(itemType)) {
                 sourceOp = createCastOp(spec, dataset.getDatasetType());
                 spec.connect(new OneToOneConnectorDescriptor(spec), primaryScanOp, 0, sourceOp, 0);
             }
@@ -369,10 +370,11 @@ public class SecondaryRTreeOperationsHelper extends SecondaryIndexOperationsHelp
             }
 
             // Sort by secondary keys.
-            ExternalSortOperatorDescriptor sortOp = createSortOp(spec,
-                    new IBinaryComparatorFactory[] {
-                            AqlMetadataProvider.proposeLinearizer(keyType, secondaryComparatorFactories.length) },
-                    isPointMBR ? secondaryRecDescForPointMBR : secondaryRecDesc);
+            ExternalSortOperatorDescriptor sortOp =
+                    createSortOp(spec,
+                            new IBinaryComparatorFactory[] { AqlMetadataProvider.proposeLinearizer(keyType,
+                                    secondaryComparatorFactories.length) },
+                            isPointMBR ? secondaryRecDescForPointMBR : secondaryRecDesc);
             AsterixStorageProperties storageProperties = propertiesProvider.getStorageProperties();
 
             // Create the dataflow helper factory
@@ -478,27 +480,27 @@ public class SecondaryRTreeOperationsHelper extends SecondaryIndexOperationsHelp
                     AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER, LSMRTreeIOOperationCallbackFactory.INSTANCE,
                     AqlMetadataProvider.proposeLinearizer(keyType, secondaryComparatorFactories.length), rtreeFields,
                     filterTypeTraits, filterCmpFactories, secondaryFilterFields, !temp, isPointMBR);
-            compactOp = new LSMTreeIndexCompactOperatorDescriptor(spec,
-                    AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER,
-                    AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER, secondaryFileSplitProvider, secondaryTypeTraits,
-                    secondaryComparatorFactories, secondaryBloomFilterKeyFields, idff,
-                    NoOpOperationCallbackFactory.INSTANCE);
+            compactOp =
+                    new LSMTreeIndexCompactOperatorDescriptor(spec, AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER,
+                            AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER, secondaryFileSplitProvider,
+                            secondaryTypeTraits, secondaryComparatorFactories, secondaryBloomFilterKeyFields, idff,
+                            NoOpOperationCallbackFactory.INSTANCE);
         } else {
             // External dataset
-            compactOp = new LSMTreeIndexCompactOperatorDescriptor(spec,
-                    AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER,
-                    AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER, secondaryFileSplitProvider, secondaryTypeTraits,
-                    secondaryComparatorFactories, secondaryBloomFilterKeyFields,
-                    new ExternalRTreeDataflowHelperFactory(valueProviderFactories, RTreePolicyType.RTREE,
-                            primaryComparatorFactories, mergePolicyFactory, mergePolicyFactoryProperties,
-                            new SecondaryIndexOperationTrackerProvider(dataset.getDatasetId()),
-                            AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER,
-                            LSMRTreeIOOperationCallbackFactory.INSTANCE,
-                            AqlMetadataProvider.proposeLinearizer(keyType, secondaryComparatorFactories.length),
-                            storageProperties.getBloomFilterFalsePositiveRate(),
-                            new int[] { numNestedSecondaryKeyFields },
-                            ExternalDatasetsRegistry.INSTANCE.getDatasetVersion(dataset), true, isPointMBR),
-                    NoOpOperationCallbackFactory.INSTANCE);
+            compactOp =
+                    new LSMTreeIndexCompactOperatorDescriptor(spec, AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER,
+                            AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER, secondaryFileSplitProvider,
+                            secondaryTypeTraits, secondaryComparatorFactories, secondaryBloomFilterKeyFields,
+                            new ExternalRTreeDataflowHelperFactory(valueProviderFactories, RTreePolicyType.RTREE,
+                                    primaryComparatorFactories, mergePolicyFactory, mergePolicyFactoryProperties,
+                                    new SecondaryIndexOperationTrackerProvider(dataset.getDatasetId()),
+                                    AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER,
+                                    LSMRTreeIOOperationCallbackFactory.INSTANCE,
+                                    AqlMetadataProvider.proposeLinearizer(keyType, secondaryComparatorFactories.length),
+                                    storageProperties.getBloomFilterFalsePositiveRate(),
+                                    new int[] { numNestedSecondaryKeyFields },
+                                    ExternalDatasetsRegistry.INSTANCE.getDatasetVersion(dataset), true, isPointMBR),
+                            NoOpOperationCallbackFactory.INSTANCE);
         }
 
         AlgebricksPartitionConstraintHelper.setPartitionConstraintInJobSpec(spec, compactOp,

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/java/org/apache/asterix/runtime/NullMissingTest.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/runtime/NullMissingTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/runtime/NullMissingTest.java
index d4b50a4..d30ffd9 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/runtime/NullMissingTest.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/runtime/NullMissingTest.java
@@ -47,15 +47,15 @@ public class NullMissingTest {
             String className = func.getClass().getName();
             // We test all generated functions except
             // record functions, which requires type settings (we test them in runtime tests);
-            if (className.contains("generated") && !className.contains("record")) {
+            if (className.contains("generated") && !className.contains("record") && !className.contains("Cast")) {
                 testFunction(func);
             }
         }
     }
 
     private void testFunction(IFunctionDescriptorFactory funcFactory) throws Exception {
-        AbstractScalarFunctionDynamicDescriptor funcDesc = (AbstractScalarFunctionDynamicDescriptor) funcFactory
-                .createFunctionDescriptor();
+        AbstractScalarFunctionDynamicDescriptor funcDesc =
+                (AbstractScalarFunctionDynamicDescriptor) funcFactory.createFunctionDescriptor();
         int inputArity = funcDesc.getIdentifier().getArity();
         Iterator<IScalarEvaluatorFactory[]> argEvalFactoryIterator = getArgCombinations(inputArity);
         int index = 0;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/optimizerts/queries/tpch/q12_shipping.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/tpch/q12_shipping.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/tpch/q12_shipping.sqlpp
new file mode 100644
index 0000000..b1a8cc1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/tpch/q12_shipping.sqlpp
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+
+DROP database tpch IF EXISTS;
+CREATE  database tpch;
+
+USE tpch;
+
+
+CREATE TYPE LineItemType AS {
+  l_linenumber : int32
+}
+
+CREATE TYPE OrderType AS {
+  o_orderkey : int32
+}
+
+CREATE TABLE LineItem(LineItemType) PRIMARY KEY l_linenumber;
+
+CREATE TABLE Orders(OrderType) PRIMARY KEY o_orderkey;
+
+/** The plan tests that the expression for different switch-case branches are not extracted.*/
+SELECT l.l_shipmode,
+       sum(CASE
+             WHEN o.o_orderpriority = '1-URGENT' or o.o_orderpriority = '2-HIGH' THEN 1 +  o.o_orderpriority * 0
+             ELSE 0 + o.o_orderpriority * 0
+           END) high_line_count,
+       sum(CASE o.o_orderpriority = '1-URGENT' or o.o_orderpriority = '2-HIGH'
+             WHEN true THEN 0 + o.o_orderpriority * 0
+             ELSE 1 +  o.o_orderpriority * 0
+           END) low_line_count
+FROM  LineItem l,
+      Orders o
+WHERE o.o_orderkey = l.l_orderkey AND l.l_commitdate < l.l_receiptdate AND
+      l.l_shipdate < l.l_commitdate AND l.l_receiptdate >= '1994-01-01' AND
+      l.l_receiptdate < '1995-01-01' AND (l.l_shipmode = 'MAIL' OR l.l_shipmode = 'SHIP')
+GROUP BY l.l_shipmode
+ORDER BY l.l_shipmode
+;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/optimizerts/results/query-ASTERIXDB-1203.plan
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/query-ASTERIXDB-1203.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/query-ASTERIXDB-1203.plan
index 9dc7a8a..b090c13 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/query-ASTERIXDB-1203.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/query-ASTERIXDB-1203.plan
@@ -16,7 +16,8 @@
                                     -- ASSIGN  |LOCAL|
                                       -- ASSIGN  |LOCAL|
                                         -- STREAM_SELECT  |LOCAL|
-                                          -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                          -- ASSIGN  |LOCAL|
+                                            -- NESTED_TUPLE_SOURCE  |LOCAL|
                         }
                   -- SUBPLAN  |PARTITIONED|
                           {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/optimizerts/results/query-ASTERIXDB-865.plan
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/query-ASTERIXDB-865.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/query-ASTERIXDB-865.plan
index 6ff5cee..914a23b 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/query-ASTERIXDB-865.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/query-ASTERIXDB-865.plan
@@ -17,7 +17,8 @@
                                       -- UNNEST  |LOCAL|
                                         -- ASSIGN  |LOCAL|
                                           -- STREAM_SELECT  |LOCAL|
-                                            -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                            -- ASSIGN  |LOCAL|
+                                              -- NESTED_TUPLE_SOURCE  |LOCAL|
                               }
                         -- SUBPLAN  |PARTITIONED|
                                 {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpch/q12_shipping.plan
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpch/q12_shipping.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpch/q12_shipping.plan
new file mode 100644
index 0000000..7c1af83
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpch/q12_shipping.plan
@@ -0,0 +1,43 @@
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    -- STREAM_PROJECT  |PARTITIONED|
+      -- ASSIGN  |PARTITIONED|
+        -- SORT_MERGE_EXCHANGE [$$3(ASC) ]  |PARTITIONED|
+          -- PRE_CLUSTERED_GROUP_BY[$$94]  |PARTITIONED|
+                  {
+                    -- AGGREGATE  |LOCAL|
+                      -- NESTED_TUPLE_SOURCE  |LOCAL|
+                  }
+            -- HASH_PARTITION_MERGE_EXCHANGE MERGE:[$$94(ASC)] HASH:[$$94]  |PARTITIONED|
+              -- SORT_GROUP_BY[$$76]  |PARTITIONED|
+                      {
+                        -- AGGREGATE  |LOCAL|
+                          -- NESTED_TUPLE_SOURCE  |LOCAL|
+                      }
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  -- STREAM_PROJECT  |PARTITIONED|
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      -- HYBRID_HASH_JOIN [$$83][$$76]  |PARTITIONED|
+                        -- HASH_PARTITION_EXCHANGE [$$83]  |PARTITIONED|
+                          -- UNNEST  |UNPARTITIONED|
+                            -- EMPTY_TUPLE_SOURCE  |UNPARTITIONED|
+                        -- HASH_PARTITION_EXCHANGE [$$76]  |PARTITIONED|
+                          -- STREAM_PROJECT  |PARTITIONED|
+                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                              -- HYBRID_HASH_JOIN [$$85][$$80]  |PARTITIONED|
+                                -- HASH_PARTITION_EXCHANGE [$$85]  |PARTITIONED|
+                                  -- STREAM_PROJECT  |PARTITIONED|
+                                    -- STREAM_SELECT  |PARTITIONED|
+                                      -- ASSIGN  |PARTITIONED|
+                                        -- STREAM_PROJECT  |PARTITIONED|
+                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                            -- DATASOURCE_SCAN  |PARTITIONED|
+                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                  -- STREAM_PROJECT  |PARTITIONED|
+                                    -- ASSIGN  |PARTITIONED|
+                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                        -- DATASOURCE_SCAN  |PARTITIONED|
+                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/IfInFLOWGR.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/IfInFLOWGR.sqlpp b/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/IfInFLOWGR.sqlpp
index 294730f..1945567 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/IfInFLOWGR.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/IfInFLOWGR.sqlpp
@@ -17,9 +17,10 @@
  * under the License.
  */
 
-select element if ((i > j))
-    then i
+select element
+    case when i > j then i
     else j
+    end
 from  [1,2,30,40] as i,
       {{4,5,6}} as j
 ;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/IfThenElse.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/IfThenElse.sqlpp b/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/IfThenElse.sqlpp
index f346d1a..877c27a 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/IfThenElse.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/IfThenElse.sqlpp
@@ -17,6 +17,8 @@
  * under the License.
  */
 
-select element if ((2 > 1))
-    then 20
-    else 10;
+select element
+    case 2 > 1
+    when true then 20
+    else 10
+    end;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/functionDecl2.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/functionDecl2.sqlpp b/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/functionDecl2.sqlpp
index ddda48e..8c5e82a 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/functionDecl2.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/functionDecl2.sqlpp
@@ -18,7 +18,7 @@
  */
 
 declare function GT(a,b) {
-if ((a > b))
-    then true
+    case when a > b then true
     else false
+    end
 };

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/nestedFLWOGR1.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/nestedFLWOGR1.sqlpp b/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/nestedFLWOGR1.sqlpp
index 704f348..7449562 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/nestedFLWOGR1.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/nestedFLWOGR1.sqlpp
@@ -19,9 +19,10 @@
 
 select element (
     select element k
-    from  if ((i > j))
-        then i
-        else j as k
+    from  case i > j
+            when true then i
+            else j
+          end as k
     where (k < 10)
 )
 from  [1,2,30,40] as i,

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/nestedFLWOGR2.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/nestedFLWOGR2.sqlpp b/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/nestedFLWOGR2.sqlpp
index 0abbf80..13e0259 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/nestedFLWOGR2.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/parserts/queries_sqlpp/nestedFLWOGR2.sqlpp
@@ -19,9 +19,11 @@
 
 select element (
     select element k
-    from  if ((i > j))
-        then i
-        else j as k
+    from  case
+           when i > j then i
+           else j
+          end
+          as k
     where (k < 10)
 )
 from  [1,2,30,(

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfInFLOWGR.ast
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfInFLOWGR.ast b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfInFLOWGR.ast
index 947c2d4..58fe98b 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfInFLOWGR.ast
+++ b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfInFLOWGR.ast
@@ -1,17 +1,17 @@
 Query:
 SELECT ELEMENT [
-IfExpr [
-  Condition:
-    OperatorExpr [
+CASE    LiteralExpr [TRUE]
+
+WHEN     OperatorExpr [
       Variable [ Name=$i ]
       >
       Variable [ Name=$j ]
     ]
-  Then:
-    Variable [ Name=$i ]
-  Else:
-    Variable [ Name=$j ]
-]
+THEN     Variable [ Name=$i ]
+
+ELSE     Variable [ Name=$j ]
+
+END
 ]
 FROM [  OrderedListConstructor [
     LiteralExpr [LONG] [1]

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfThenElse.ast
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfThenElse.ast b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfThenElse.ast
index 8c3462e..cf95780 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfThenElse.ast
+++ b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/IfThenElse.ast
@@ -1,15 +1,15 @@
 Query:
 SELECT ELEMENT [
-IfExpr [
-  Condition:
-    OperatorExpr [
+CASE    OperatorExpr [
       LiteralExpr [LONG] [2]
       >
       LiteralExpr [LONG] [1]
     ]
-  Then:
-    LiteralExpr [LONG] [20]
-  Else:
-    LiteralExpr [LONG] [10]
-]
+
+WHEN     LiteralExpr [TRUE]
+THEN     LiteralExpr [LONG] [20]
+
+ELSE     LiteralExpr [LONG] [10]
+
+END
 ]

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/functionDecl2.ast
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/functionDecl2.ast b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/functionDecl2.ast
index de37697..33b1f55 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/functionDecl2.ast
+++ b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/functionDecl2.ast
@@ -1,15 +1,15 @@
 FunctionDecl GT([$a, $b]) {
-  IfExpr [
-    Condition:
-      OperatorExpr [
+  CASE      LiteralExpr [TRUE]
+
+  WHEN       OperatorExpr [
         Variable [ Name=$a ]
         >
         Variable [ Name=$b ]
       ]
-    Then:
-      LiteralExpr [TRUE]
-    Else:
-      LiteralExpr [FALSE]
-  ]
+  THEN       LiteralExpr [TRUE]
+
+  ELSE       LiteralExpr [FALSE]
+
+  END
 }
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR1.ast
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR1.ast b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR1.ast
index 2af8be1..42831c4 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR1.ast
+++ b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR1.ast
@@ -4,18 +4,18 @@ SELECT ELEMENT [
   SELECT ELEMENT [
   Variable [ Name=$k ]
   ]
-  FROM [    IfExpr [
-      Condition:
-        OperatorExpr [
+  FROM [    CASE        OperatorExpr [
           Variable [ Name=$i ]
           >
           Variable [ Name=$j ]
         ]
-      Then:
-        Variable [ Name=$i ]
-      Else:
-        Variable [ Name=$j ]
-    ]
+
+    WHEN         LiteralExpr [TRUE]
+    THEN         Variable [ Name=$i ]
+
+    ELSE         Variable [ Name=$j ]
+
+    END
     AS Variable [ Name=$k ]
   ]
   Where

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR2.ast
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR2.ast b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR2.ast
index 5e5ac9a..60f5465 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR2.ast
+++ b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR2.ast
@@ -4,18 +4,18 @@ SELECT ELEMENT [
   SELECT ELEMENT [
   Variable [ Name=$k ]
   ]
-  FROM [    IfExpr [
-      Condition:
-        OperatorExpr [
+  FROM [    CASE        LiteralExpr [TRUE]
+
+    WHEN         OperatorExpr [
           Variable [ Name=$i ]
           >
           Variable [ Name=$j ]
         ]
-      Then:
-        Variable [ Name=$i ]
-      Else:
-        Variable [ Name=$j ]
-    ]
+    THEN         Variable [ Name=$i ]
+
+    ELSE         Variable [ Name=$j ]
+
+    END
     AS Variable [ Name=$k ]
   ]
   Where

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/ifthenelse_02/ifthenelse_01.3.query.aql
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/ifthenelse_02/ifthenelse_01.3.query.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/ifthenelse_02/ifthenelse_01.3.query.aql
new file mode 100644
index 0000000..c7aad30
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/ifthenelse_02/ifthenelse_01.3.query.aql
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+if (null=1) then
+    20
+else
+    10

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/query-ASTERIXDB-819-2/query-ASTERIXDB-819-2.1.query.aql
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/query-ASTERIXDB-819-2/query-ASTERIXDB-819-2.1.query.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/query-ASTERIXDB-819-2/query-ASTERIXDB-819-2.1.query.aql
new file mode 100644
index 0000000..a8b3789
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/query-ASTERIXDB-819-2/query-ASTERIXDB-819-2.1.query.aql
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+if (1!=1.0) then
+"result"
+else
+{ "type": "object" }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/query-ASTERIXDB-819/query-ASTERIXDB-819.1.query.aql
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/query-ASTERIXDB-819/query-ASTERIXDB-819.1.query.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/query-ASTERIXDB-819/query-ASTERIXDB-819.1.query.aql
new file mode 100644
index 0000000..4f54f33
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/query-ASTERIXDB-819/query-ASTERIXDB-819.1.query.aql
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+if (true) then
+null
+else
+1
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_01/case_01.1.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_01/case_01.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_01/case_01.1.query.sqlpp
new file mode 100644
index 0000000..c2a4cea
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_01/case_01.1.query.sqlpp
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+SELECT
+  CASE t
+    WHEN 0 THEN 0.0
+    WHEN NULL THEN -1
+    WHEN MISSING THEN -2
+    ELSE 2.0/t
+  END
+FROM [0, 1, 2, 4, NULL, [0][-1]] t;
+

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_02/case_02.1.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_02/case_02.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_02/case_02.1.query.sqlpp
new file mode 100644
index 0000000..ab19bcb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_02/case_02.1.query.sqlpp
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+SELECT
+  CASE
+    WHEN t=0 THEN 0.0
+    WHEN t IS NULL THEN -1
+    WHEN t IS MISSING THEN -2
+    ELSE 2.0/t
+  END
+FROM [0, 1, 2, 4, NULL, [0][-1]] t;
+
+

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_03/case_03.1.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_03/case_03.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_03/case_03.1.query.sqlpp
new file mode 100644
index 0000000..7c3e566
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_03/case_03.1.query.sqlpp
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+SELECT
+  CASE
+    WHEN t = 0 THEN (SELECT 0 AS r)
+    WHEN t IS NULL THEN (SELECT -1 AS r)
+    WHEN t IS MISSING THEN (SELECT -2 AS r)
+    ELSE (SELECT -3 AS r)
+  END
+FROM [0, 1, 2, 4, NULL, [0][-1]] t;
+

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_04/case_04.1.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_04/case_04.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_04/case_04.1.query.sqlpp
new file mode 100644
index 0000000..154e611
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_04/case_04.1.query.sqlpp
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+SELECT
+  CASE
+    WHEN t = 0 THEN [0]
+    WHEN t IS NULL THEN (SELECT -1)
+    WHEN t IS MISSING THEN (SELECT -2)
+    ELSE 2.0/t
+  END
+FROM [0, 1, 2, 4, NULL, [0][-1]] t;
+

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_05/case_05.1.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_05/case_05.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_05/case_05.1.query.sqlpp
new file mode 100644
index 0000000..32030a7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_05/case_05.1.query.sqlpp
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+SELECT
+  CASE
+    WHEN t = 0 THEN [0]
+    WHEN t IS NULL THEN (SELECT -1)
+    WHEN t IS MISSING THEN (SELECT -2)
+    WHEN t =1 THEN NULL
+    WHEN t=2 THEN MISSING
+    ELSE 2.0/t
+  END
+FROM [0, 1, 2, 4, NULL, [0][-1]] t;
+

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_06/case_06.1.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_06/case_06.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_06/case_06.1.query.sqlpp
new file mode 100644
index 0000000..5bf2786
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_06/case_06.1.query.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+SELECT
+  CASE
+    WHEN t = 0 THEN MISSING
+    ELSE NULL
+  END
+FROM [0, 1, 2, 4, NULL, [0][-1]] t;
+

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_07/case_07.1.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_07/case_07.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_07/case_07.1.query.sqlpp
new file mode 100644
index 0000000..4850047
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/case_07/case_07.1.query.sqlpp
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+SELECT
+  CASE
+    WHEN t = 0 THEN [0]
+    WHEN t IS NULL THEN (SELECT -1)
+    WHEN t IS MISSING THEN (SELECT -2)
+    WHEN t =1 THEN NULL
+    WHEN t=2 THEN MISSING
+    WHEN t IS UNKNOWN THEN (SELECT -3) // Should never enter this THEN branch.
+    ELSE 2.0/t
+  END
+FROM [0, 1, 2, 4, NULL, [0][-1]] t;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/ifthenelse_01/ifthenelse_01.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/ifthenelse_01/ifthenelse_01.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/ifthenelse_01/ifthenelse_01.3.query.sqlpp
index 609ec27..e96b458 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/ifthenelse_01/ifthenelse_01.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/ifthenelse_01/ifthenelse_01.3.query.sqlpp
@@ -17,9 +17,13 @@
  * under the License.
  */
 
-use test;
+USE test;
 
 
-select element if ((2 > 1))
-    then 20
-    else 10;
+SELECT ELEMENT
+    CASE 2>1
+     WHEN TRUE THEN 20
+     ELSE 10
+    END
+;
+

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/open-closed/query-issue258/query-issue258.2.update.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/open-closed/query-issue258/query-issue258.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/open-closed/query-issue258/query-issue258.2.update.sqlpp
index b662786..2b009ae 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/open-closed/query-issue258/query-issue258.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/open-closed/query-issue258/query-issue258.2.update.sqlpp
@@ -23,14 +23,16 @@
  * Date         : 21 May 2013
  */
 
-use test;
+USE test;
 
 
-insert into ds1
-if ((coll_count((
+INSERT INTO ds1
+CASE
+  WHEN coll_count((
       select element x
       from  ds2 as x
       where (x.id = 10)
-  )) <= 0))
-then {'id':10}
-else {'id':5};
+  )) <= 0
+  THEN {'id':10}
+  ELSE {'id':5}
+END;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q08_national_market_share/q08_national_market_share.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q08_national_market_share/q08_national_market_share.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q08_national_market_share/q08_national_market_share.3.query.sqlpp
index 3c1a921..a8b4bac 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q08_national_market_share/q08_national_market_share.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q08_national_market_share/q08_national_market_share.3.query.sqlpp
@@ -21,7 +21,7 @@ use tpch;
 
 
 select element {'year':year,'mkt_share':(tpch.coll_sum((
-          select element tpch.`switch-case`((i.s_name = 'BRAZIL'),true,i.revenue,false,0.0)
+          select element case when i.s_name = 'BRAZIL' then i.revenue else 0.0 end
           from  t as i
       )) / tpch.coll_sum((
           select element i.revenue

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.query.sqlpp
index 879f936..c576c6c 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.query.sqlpp
@@ -21,10 +21,16 @@ use tpch;
 
 
 select element {'l_shipmode':l_shipmode,'high_line_count':tpch.coll_sum((
-        select element tpch.`switch-case`(((i.o_orderpriority = '1-URGENT') or (i.o_orderpriority = '2-HIGH')),true,1,false,0)
+        select element case i.o_orderpriority = '1-URGENT' or i.o_orderpriority = '2-HIGH'
+                       when true then 1
+                       when false then 0
+                       end
         from  o as i
     )),'low_line_count':tpch.coll_sum((
-        select element tpch.`switch-case`(((i.o_orderpriority = '1-URGENT') or (i.o_orderpriority = '2-HIGH')),true,0,false,1)
+        select element case i.o_orderpriority = '1-URGENT' or i.o_orderpriority = '2-HIGH'
+                       when true then 0
+                       when false then 1
+                       end
         from  o as i
     ))}
 from  LineItem as l,

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
index eb556b1..7a14b25 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
@@ -21,7 +21,10 @@ use tpch;
 
 
 select element (100.0 * tpch.coll_sum((
-      select element tpch.`switch-case`(i.p_type like 'PROMO%',true,(i.l_extendedprice * (1 - i.l_discount)),false,0.0)
+      select element case i.p_type like 'PROMO%'
+                     when true then i.l_extendedprice * (1 - i.l_discount)
+                     when false then 0.0
+                     end
       from  lp as i
   )) / tpch.coll_sum((
       select element (i.l_extendedprice * (1 - i.l_discount))

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-sugar/q08_national_market_share/q08_national_market_share.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-sugar/q08_national_market_share/q08_national_market_share.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-sugar/q08_national_market_share/q08_national_market_share.3.query.sqlpp
index df23284..3c69b1c 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-sugar/q08_national_market_share/q08_national_market_share.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-sugar/q08_national_market_share/q08_national_market_share.3.query.sqlpp
@@ -21,8 +21,7 @@ USE tpch;
 
 
 SELECT  year,
-        sum( `switch-case`(s_name = 'BRAZIL', true, revenue, false, 0.0) )
-        / sum(revenue) AS mkt_share
+        SUM( CASE s_name = 'BRAZIL' WHEN true THEN revenue ELSE 0.0 END ) / SUM(revenue) AS mkt_share
 FROM  (
         SELECT o_year AS year,
                l_extendedprice * (1 - l_discount) AS revenue,

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-sugar/q12_shipping/q12_shipping.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-sugar/q12_shipping/q12_shipping.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-sugar/q12_shipping/q12_shipping.3.query.sqlpp
index 0d778e4..5d0378a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-sugar/q12_shipping/q12_shipping.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-sugar/q12_shipping/q12_shipping.3.query.sqlpp
@@ -17,12 +17,12 @@
  * under the License.
  */
 
-use tpch;
+USE tpch;
 
 
 SELECT l_shipmode,
-       sum(`switch-case`(o_orderpriority = '1-URGENT' or o_orderpriority = '2-HIGH',true,1,false,0)) high_line_count,
-       sum(`switch-case`(o_orderpriority = '1-URGENT' or o_orderpriority = '2-HIGH',true,0,false,1)) low_line_count
+       sum(CASE WHEN o_orderpriority = '1-URGENT' or o_orderpriority = '2-HIGH' THEN 1 ELSE 0 END) high_line_count,
+       sum(CASE o_orderpriority = '1-URGENT' or o_orderpriority = '2-HIGH' WHEN true THEN 0 ELSE 1 END) low_line_count
 FROM  LineItem,
       Orders
 WHERE o_orderkey = l_orderkey AND l_commitdate < l_receiptdate AND

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-sugar/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-sugar/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-sugar/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
index 1c10baf..d359369 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-sugar/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-sugar/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
@@ -20,9 +20,9 @@
 use tpch;
 
 
-select element 100.0 *
-     sum(`switch-case`(p_type LIKE 'PROMO%',true, l_extendedprice * (1 - l_discount), false, 0.0))
-     / sum(l_extendedprice * (1 - l_discount))
+SELECT ELEMENT 100.0 *
+     SUM( CASE WHEN p_type LIKE 'PROMO%' THEN l_extendedprice * (1 - l_discount) ELSE 0.0 END )
+     / SUM(l_extendedprice * (1 - l_discount))
 FROM  LineItem,
       Part
 WHERE l_partkey = p_partkey AND l_shipdate >= '1995-09-01' AND l_shipdate < '1995-10-01'

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql/q08_national_market_share/q08_national_market_share.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql/q08_national_market_share/q08_national_market_share.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql/q08_national_market_share/q08_national_market_share.3.query.sqlpp
index 89afd7d..52fd1eb 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql/q08_national_market_share/q08_national_market_share.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql/q08_national_market_share/q08_national_market_share.3.query.sqlpp
@@ -21,7 +21,7 @@ USE tpch;
 
 
 SELECT  year AS year,
-        sum( `switch-case`(t.s_name = 'BRAZIL', true, t.revenue, false, 0.0) )
+        sum( case when t.s_name = 'BRAZIL' then t.revenue else 0.0 end )
         / sum(t.revenue) AS mkt_share
 FROM  (
         SELECT o_year AS year,

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql/q12_shipping/q12_shipping.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql/q12_shipping/q12_shipping.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql/q12_shipping/q12_shipping.3.query.sqlpp
index 3be8e22..227a576 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql/q12_shipping/q12_shipping.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql/q12_shipping/q12_shipping.3.query.sqlpp
@@ -21,8 +21,8 @@ use tpch;
 
 
 SELECT l_shipmode l_shipmode,
-       sum(`switch-case`(o.o_orderpriority = '1-URGENT' or o.o_orderpriority = '2-HIGH',true,1,false,0)) high_line_count,
-       sum(`switch-case`(o.o_orderpriority = '1-URGENT' or o.o_orderpriority = '2-HIGH',true,0,false,1)) low_line_count
+       sum(case when o.o_orderpriority = '1-URGENT' or o.o_orderpriority = '2-HIGH' then 1 else 0 end) high_line_count,
+       sum(case when o.o_orderpriority = '1-URGENT' or o.o_orderpriority = '2-HIGH' then 0 else 1 end) low_line_count
 FROM  LineItem l,
       Orders o
 WHERE o.o_orderkey = l.l_orderkey AND l.l_commitdate < l.l_receiptdate AND

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
index dc26e42..0d11017 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
@@ -21,7 +21,7 @@ use tpch;
 
 
 select element 100.0 *
-     sum(`switch-case`(p.p_type like 'PROMO%',true,(l.l_extendedprice * (1 - l.l_discount)),false,0.0))
+     sum( case when p.p_type like 'PROMO%' then l.l_extendedprice * (1 - l.l_discount) else 0.0 end)
      / sum(l.l_extendedprice * (1 - l.l_discount))
 FROM  LineItem l,
       Part p

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q08_national_market_share/q08_national_market_share.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q08_national_market_share/q08_national_market_share.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q08_national_market_share/q08_national_market_share.3.query.sqlpp
index 3c1a921..b9b739d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q08_national_market_share/q08_national_market_share.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q08_national_market_share/q08_national_market_share.3.query.sqlpp
@@ -21,7 +21,7 @@ use tpch;
 
 
 select element {'year':year,'mkt_share':(tpch.coll_sum((
-          select element tpch.`switch-case`((i.s_name = 'BRAZIL'),true,i.revenue,false,0.0)
+          select element case i.s_name = 'BRAZIL' when true then i.revenue when false then 0.0 end
           from  t as i
       )) / tpch.coll_sum((
           select element i.revenue

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q12_shipping/q12_shipping.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q12_shipping/q12_shipping.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q12_shipping/q12_shipping.3.query.sqlpp
index 879f936..395279b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q12_shipping/q12_shipping.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q12_shipping/q12_shipping.3.query.sqlpp
@@ -21,10 +21,16 @@ use tpch;
 
 
 select element {'l_shipmode':l_shipmode,'high_line_count':tpch.coll_sum((
-        select element tpch.`switch-case`(((i.o_orderpriority = '1-URGENT') or (i.o_orderpriority = '2-HIGH')),true,1,false,0)
+        select element case
+                        when i.o_orderpriority = '1-URGENT' or i.o_orderpriority = '2-HIGH' then 1
+                        else 0
+                        end
         from  o as i
     )),'low_line_count':tpch.coll_sum((
-        select element tpch.`switch-case`(((i.o_orderpriority = '1-URGENT') or (i.o_orderpriority = '2-HIGH')),true,0,false,1)
+        select element case
+                         when i.o_orderpriority = '1-URGENT' or i.o_orderpriority = '2-HIGH' then 0
+                         else 1
+                        end
         from  o as i
     ))}
 from  LineItem as l,

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
index eb556b1..5de0352 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
@@ -21,7 +21,10 @@ use tpch;
 
 
 select element (100.0 * tpch.coll_sum((
-      select element tpch.`switch-case`(i.p_type like 'PROMO%',true,(i.l_extendedprice * (1 - i.l_discount)),false,0.0)
+      select element case
+                       when i.p_type like 'PROMO%' then i.l_extendedprice * (1 - i.l_discount)
+                       else 0.0
+                     end
       from  lp as i
   )) / tpch.coll_sum((
       select element (i.l_extendedprice * (1 - i.l_discount))

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q08_national_market_share/q08_national_market_share.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q08_national_market_share/q08_national_market_share.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q08_national_market_share/q08_national_market_share.3.query.sqlpp
index aaef8e5..70b59e0 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q08_national_market_share/q08_national_market_share.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q08_national_market_share/q08_national_market_share.3.query.sqlpp
@@ -21,7 +21,7 @@ use tpch;
 
 
 select element {'year':year,'mkt_share':(COLL_SUM((
-          select element tpch.`switch-case`((i.s_name = 'BRAZIL'),true,i.revenue,false,0.0)
+          select element case i.s_name = 'BRAZIL' when true then i.revenue when false then 0.0 end
           from  t as i
       )) / COLL_SUM((
           select element i.revenue

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q12_shipping/q12_shipping.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q12_shipping/q12_shipping.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q12_shipping/q12_shipping.3.query.sqlpp
index c089f72..58d0c9e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q12_shipping/q12_shipping.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q12_shipping/q12_shipping.3.query.sqlpp
@@ -21,10 +21,11 @@ use tpch;
 
 
 select element {'l_shipmode':l_shipmode,'high_line_count':COLL_SUM((
-        select element tpch.`switch-case`(((i.o_orderpriority = '1-URGENT') or (i.o_orderpriority = '2-HIGH')),true,1,false,0)
+        select element 
+            CASE i.o_orderpriority = '1-URGENT' OR i.o_orderpriority = '2-HIGH' WHEN true THEN 1 WHEN false THEN 0 END
         from  o as i
     )),'low_line_count':COLL_SUM((
-        select element tpch.`switch-case`(((i.o_orderpriority = '1-URGENT') or (i.o_orderpriority = '2-HIGH')),true,0,false,1)
+        select element case when i.o_orderpriority = '1-URGENT' OR i.o_orderpriority = '2-HIGH' then 0 else 1 end
         from  o as i
     ))}
 from  LineItem as l,

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
index ba7de7d..32ab76a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
@@ -21,7 +21,7 @@ use tpch;
 
 
 select element (100.0 * COLL_SUM((
-      select element tpch.`switch-case`(i.p_type like 'PROMO%',true,(i.l_extendedprice * (1 - i.l_discount)),false,0.0)
+      select element case i.p_type like 'PROMO%' when true then i.l_extendedprice * (1 - i.l_discount) else 0.0 end
       from  lp as i
   )) / COLL_SUM((
       select element (i.l_extendedprice * (1 - i.l_discount))

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/query-issue218-2/query-issue218-2.1.ddl.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/query-issue218-2/query-issue218-2.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/query-issue218-2/query-issue218-2.1.ddl.sqlpp
index f535ffe..6942fc8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/query-issue218-2/query-issue218-2.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/query-issue218-2/query-issue218-2.1.ddl.sqlpp
@@ -28,8 +28,8 @@ create database test;
 
 create function test.computeBonus(pbcRating,salary)
 {
-   if (pbcRating = 1) then
-        salary * 0.25
-   else
-        salary * 0.10
+   CASE
+      WHEN pbcRating = 1 THEN salary * 0.25
+      ELSE salary * 0.10
+   END
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/query-issue218/query-issue218.1.ddl.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/query-issue218/query-issue218.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/query-issue218/query-issue218.1.ddl.sqlpp
index bc22967..28f84bf 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/query-issue218/query-issue218.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/user-defined-functions/query-issue218/query-issue218.1.ddl.sqlpp
@@ -28,8 +28,8 @@ create database test;
 
 create function test.computeBonus(pbcRating, salary)
 {
-   if (pbcRating = 1) then
-        salary * 0.25
-   else
-        salary * 0.10
+   CASE
+      WHEN pbcRating = 1 THEN salary * 0.25
+      ELSE salary * 0.10
+   END
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_01/case_01.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_01/case_01.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_01/case_01.1.adm
new file mode 100644
index 0000000..f433f2f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_01/case_01.1.adm
@@ -0,0 +1,6 @@
+{ "$1": 0.0 }
+{ "$1": 2.0 }
+{ "$1": 1.0 }
+{ "$1": 0.5 }
+{ "$1": null }
+{  }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_02/case_02.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_02/case_02.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_02/case_02.1.adm
new file mode 100644
index 0000000..7c61d7b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_02/case_02.1.adm
@@ -0,0 +1,6 @@
+{ "$1": 0.0 }
+{ "$1": 2.0 }
+{ "$1": 1.0 }
+{ "$1": 0.5 }
+{ "$1": -1 }
+{ "$1": -2 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_03/case_03.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_03/case_03.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_03/case_03.1.adm
new file mode 100644
index 0000000..bcced75
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_03/case_03.1.adm
@@ -0,0 +1,6 @@
+{ "$1": [ { "r": 0 } ] }
+{ "$1": [ { "r": -3 } ] }
+{ "$1": [ { "r": -3 } ] }
+{ "$1": [ { "r": -3 } ] }
+{ "$1": [ { "r": -1 } ] }
+{ "$1": [ { "r": -2 } ] }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_04/case_04.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_04/case_04.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_04/case_04.1.adm
new file mode 100644
index 0000000..f2a1ae7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_04/case_04.1.adm
@@ -0,0 +1,6 @@
+{ "$1": [ 0 ] }
+{ "$1": 2.0 }
+{ "$1": 1.0 }
+{ "$1": 0.5 }
+{ "$1": [ { "$2": -1 } ] }
+{ "$1": [ { "$3": -2 } ] }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_05/case_05.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_05/case_05.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_05/case_05.1.adm
new file mode 100644
index 0000000..5d37fcc
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_05/case_05.1.adm
@@ -0,0 +1,6 @@
+{ "$1": [ 0 ] }
+{ "$1": null }
+{  }
+{ "$1": 0.5 }
+{ "$1": [ { "$2": -1 } ] }
+{ "$1": [ { "$3": -2 } ] }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_06/case_06.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_06/case_06.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_06/case_06.1.adm
new file mode 100644
index 0000000..69e44e4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/case_06/case_06.1.adm
@@ -0,0 +1,6 @@
+{  }
+{ "$1": null }
+{ "$1": null }
+{ "$1": null }
+{ "$1": null }
+{ "$1": null }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/ifthenelse_02/ifthenelse_02.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/ifthenelse_02/ifthenelse_02.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/ifthenelse_02/ifthenelse_02.1.adm
new file mode 100644
index 0000000..f599e28
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/ifthenelse_02/ifthenelse_02.1.adm
@@ -0,0 +1 @@
+10

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/query-ASTERIXDB-819-2/query-ASTERIXDB-819-2.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/query-ASTERIXDB-819-2/query-ASTERIXDB-819-2.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/query-ASTERIXDB-819-2/query-ASTERIXDB-819-2.1.adm
new file mode 100644
index 0000000..bba55dc
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/query-ASTERIXDB-819-2/query-ASTERIXDB-819-2.1.adm
@@ -0,0 +1 @@
+{ "type": "object" }


[4/4] asterixdb git commit: Support CASE expression in SQL++.

Posted by bu...@apache.org.
Support CASE expression in SQL++.

- support both simple CASE expression and searched CASE expression;
- support heterogenous return types of a CASE expression;
- remove IfElseExpression in SQL++;
- remove IfElseToSwitchCaseFunctionRule.java since the plan pattern it tries to identify is no longer right;
- unify CastRecordDescriptor and CastListDescriptor into CastTypeDescriptor;
- fix IS NULL for the case that the input is MISSING;
- let CastTypeDescriptor have a generated runtime so as to handle NULL/MISSING correctly.

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


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

Branch: refs/heads/master
Commit: c8c067c58cd19052fa9c108f08e42fdfd9ae6cec
Parents: f23d86e
Author: Yingyi Bu <yi...@couchbase.com>
Authored: Mon Jul 25 23:37:19 2016 -0700
Committer: Yingyi Bu <bu...@gmail.com>
Committed: Tue Jul 26 14:21:59 2016 -0700

----------------------------------------------------------------------
 .../asterix/optimizer/base/RuleCollections.java |   4 +-
 .../rules/AsterixInlineVariablesRule.java       |   2 +-
 .../optimizer/rules/ConstantFoldingRule.java    |  19 +-
 .../rules/IfElseToSwitchCaseFunctionRule.java   | 130 --------
 .../rules/InjectToAnyTypeCastRule.java          | 145 +++++++++
 ...eDynamicTypeCastForExternalFunctionRule.java |  24 +-
 .../rules/IntroduceDynamicTypeCastRule.java     |  10 +-
 ...IntroduceSecondaryIndexInsertDeleteRule.java |   2 +-
 .../rules/typecast/StaticTypeCastUtil.java      |  14 +-
 .../LangExpressionToPlanTranslator.java         |  51 ++-
 .../SqlppExpressionToPlanTranslator.java        | 153 +++++++--
 .../translator/util/FunctionCollection.java     |  10 +-
 .../file/SecondaryBTreeOperationsHelper.java    |  54 ++--
 .../file/SecondaryIndexOperationsHelper.java    |  39 ++-
 .../SecondaryInvertedIndexOperationsHelper.java |  46 +--
 .../file/SecondaryRTreeOperationsHelper.java    | 102 +++---
 .../apache/asterix/runtime/NullMissingTest.java |   6 +-
 .../optimizerts/queries/tpch/q12_shipping.sqlpp |  56 ++++
 .../results/query-ASTERIXDB-1203.plan           |   3 +-
 .../results/query-ASTERIXDB-865.plan            |   3 +-
 .../optimizerts/results/tpch/q12_shipping.plan  |  43 +++
 .../parserts/queries_sqlpp/IfInFLOWGR.sqlpp     |   5 +-
 .../parserts/queries_sqlpp/IfThenElse.sqlpp     |   8 +-
 .../parserts/queries_sqlpp/functionDecl2.sqlpp  |   4 +-
 .../parserts/queries_sqlpp/nestedFLWOGR1.sqlpp  |   7 +-
 .../parserts/queries_sqlpp/nestedFLWOGR2.sqlpp  |   8 +-
 .../results_parser_sqlpp/IfInFLOWGR.ast         |  16 +-
 .../results_parser_sqlpp/IfThenElse.ast         |  16 +-
 .../results_parser_sqlpp/functionDecl2.ast      |  16 +-
 .../results_parser_sqlpp/nestedFLWOGR1.ast      |  16 +-
 .../results_parser_sqlpp/nestedFLWOGR2.ast      |  16 +-
 .../ifthenelse_02/ifthenelse_01.3.query.aql     |  23 ++
 .../query-ASTERIXDB-819-2.1.query.aql           |  23 ++
 .../query-ASTERIXDB-819.1.query.aql             |  23 ++
 .../misc/case_01/case_01.1.query.sqlpp          |  28 ++
 .../misc/case_02/case_02.1.query.sqlpp          |  29 ++
 .../misc/case_03/case_03.1.query.sqlpp          |  28 ++
 .../misc/case_04/case_04.1.query.sqlpp          |  28 ++
 .../misc/case_05/case_05.1.query.sqlpp          |  30 ++
 .../misc/case_06/case_06.1.query.sqlpp          |  26 ++
 .../misc/case_07/case_07.1.query.sqlpp          |  30 ++
 .../ifthenelse_01/ifthenelse_01.3.query.sqlpp   |  12 +-
 .../query-issue258.2.update.sqlpp               |  14 +-
 .../q08_national_market_share.3.query.sqlpp     |   2 +-
 .../q12_shipping/q12_shipping.3.query.sqlpp     |  10 +-
 .../q14_promotion_effect.3.query.sqlpp          |   5 +-
 .../q08_national_market_share.3.query.sqlpp     |   3 +-
 .../q12_shipping/q12_shipping.3.query.sqlpp     |   6 +-
 .../q14_promotion_effect.3.query.sqlpp          |   6 +-
 .../q08_national_market_share.3.query.sqlpp     |   2 +-
 .../q12_shipping/q12_shipping.3.query.sqlpp     |   4 +-
 .../q14_promotion_effect.3.query.sqlpp          |   2 +-
 .../q08_national_market_share.3.query.sqlpp     |   2 +-
 .../q12_shipping/q12_shipping.3.query.sqlpp     |  10 +-
 .../q14_promotion_effect.3.query.sqlpp          |   5 +-
 .../q08_national_market_share.3.query.sqlpp     |   2 +-
 .../q12_shipping/q12_shipping.3.query.sqlpp     |   5 +-
 .../q14_promotion_effect.3.query.sqlpp          |   2 +-
 .../query-issue218-2.1.ddl.sqlpp                |   8 +-
 .../query-issue218/query-issue218.1.ddl.sqlpp   |   8 +-
 .../results/misc/case_01/case_01.1.adm          |   6 +
 .../results/misc/case_02/case_02.1.adm          |   6 +
 .../results/misc/case_03/case_03.1.adm          |   6 +
 .../results/misc/case_04/case_04.1.adm          |   6 +
 .../results/misc/case_05/case_05.1.adm          |   6 +
 .../results/misc/case_06/case_06.1.adm          |   6 +
 .../misc/ifthenelse_02/ifthenelse_02.1.adm      |   1 +
 .../query-ASTERIXDB-819-2.1.adm                 |   1 +
 .../query-ASTERIXDB-819.1.adm                   |   1 +
 .../runtimets/results/null-missing/is/is.1.adm  |   2 +-
 .../misc/ifthenelse_01/ifthenelse_01.3.ast      |  16 +-
 .../q08_national_market_share.3.ast             |  31 +-
 .../q12_shipping/q12_shipping.3.ast             |  96 +++---
 .../q14_promotion_effect.3.ast                  |  50 +--
 .../q08_national_market_share.3.ast             |  34 +-
 .../tpch/q12_shipping/q12_shipping.3.ast        |  93 +++---
 .../q14_promotion_effect.3.ast                  |  47 +--
 .../src/test/resources/runtimets/testsuite.xml  |  15 +
 .../resources/runtimets/testsuite_sqlpp.xml     |  35 ++
 .../lang/aql/visitor/AQLInlineUdfsVisitor.java  |   4 +-
 .../asterix/lang/common/base/Expression.java    |   3 +-
 .../visitor/AbstractInlineUdfsVisitor.java      |  93 +++---
 .../visitor/SubstituteExpressionVisitor.java    |   2 +-
 .../lang/sqlpp/expression/CaseExpression.java   | 129 ++++++++
 .../lang/sqlpp/rewrites/SqlppQueryRewriter.java |  14 +
 .../visitor/InlineColumnAliasVisitor.java       |  14 +
 .../SqlppBuiltinFunctionRewriteVisitor.java     |  52 +++
 .../visitor/SqlppInlineUdfsVisitor.java         |  26 +-
 .../lang/sqlpp/util/SqlppRewriteUtil.java       |  10 +
 .../visitor/CheckSql92AggregateVisitor.java     |   9 +-
 .../sqlpp/visitor/CheckSubqueryVisitor.java     | 316 +++++++++++++++++++
 .../lang/sqlpp/visitor/DeepCopyVisitor.java     |  34 +-
 .../lang/sqlpp/visitor/FreeVariableVisitor.java |  37 ++-
 .../sqlpp/visitor/SqlppAstPrintVisitor.java     |  27 +-
 ...SqlppCloneAndSubstituteVariablesVisitor.java |  15 +
 .../sqlpp/visitor/SqlppFormatPrintVisitor.java  |  22 ++
 .../SqlppSubstituteExpressionsVisitor.java      |  15 +
 .../visitor/base/AbstractSqlppAstVisitor.java   |   6 +
 .../AbstractSqlppSimpleExpressionVisitor.java   |  30 +-
 .../lang/sqlpp/visitor/base/ISqlppVisitor.java  |   3 +
 .../src/main/javacc/SQLPP.html                  |   7 +-
 .../asterix-lang-sqlpp/src/main/javacc/SQLPP.jj |  42 ++-
 .../om/functions/AsterixBuiltinFunctions.java   |  14 +-
 .../impl/CastListResultTypeComputer.java        |  46 ---
 .../impl/CastRecordResultTypeComputer.java      |  40 ---
 .../om/typecomputer/impl/CastTypeComputer.java  |  46 +++
 .../typecomputer/impl/SwitchCaseComputer.java   |  33 +-
 .../common/AbstractTypeCheckEvaluator.java      |  18 +-
 .../functions/CastListDescriptor.java           | 105 ------
 .../functions/CastRecordDescriptor.java         | 102 ------
 .../functions/CastTypeDescriptor.java           | 154 +++++++++
 .../functions/IsMissingDescriptor.java          |   4 +-
 .../evaluators/functions/IsNullDescriptor.java  |   7 +-
 .../functions/IsUnknownDescriptor.java          |   6 +-
 .../functions/SwitchCaseDescriptor.java         |   7 +-
 .../runtime/formats/NonTaggedDataFormat.java    |  68 ++--
 116 files changed, 2336 insertions(+), 1086 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
index 683d722..0fba9da 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
@@ -36,7 +36,7 @@ import org.apache.asterix.optimizer.rules.ExtractDistinctByExpressionsRule;
 import org.apache.asterix.optimizer.rules.ExtractOrderExpressionsRule;
 import org.apache.asterix.optimizer.rules.FeedScanCollectionToUnnest;
 import org.apache.asterix.optimizer.rules.FuzzyEqRule;
-import org.apache.asterix.optimizer.rules.IfElseToSwitchCaseFunctionRule;
+import org.apache.asterix.optimizer.rules.InjectToAnyTypeCastRule;
 import org.apache.asterix.optimizer.rules.InlineUnnestFunctionRule;
 import org.apache.asterix.optimizer.rules.IntroduceAutogenerateIDRule;
 import org.apache.asterix.optimizer.rules.IntroduceDynamicTypeCastForExternalFunctionRule;
@@ -173,7 +173,6 @@ public final class RuleCollections {
         normalization.add(new RemoveRedundantSelectRule());
         normalization.add(new UnnestToDataScanRule());
         normalization.add(new MetaFunctionToMetaVariableRule());
-        normalization.add(new IfElseToSwitchCaseFunctionRule());
         normalization.add(new FuzzyEqRule());
         normalization.add(new SimilarityCheckRule());
         return normalization;
@@ -282,6 +281,7 @@ public final class RuleCollections {
         planCleanupRules.add(new IntroduceDynamicTypeCastForExternalFunctionRule());
         planCleanupRules.add(new RemoveUnusedAssignAndAggregateRule());
         planCleanupRules.add(new RemoveCartesianProductWithEmptyBranchRule());
+        planCleanupRules.add(new InjectToAnyTypeCastRule());
         return planCleanupRules;
     }
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/AsterixInlineVariablesRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/AsterixInlineVariablesRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/AsterixInlineVariablesRule.java
index 5486e64..74640a6 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/AsterixInlineVariablesRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/AsterixInlineVariablesRule.java
@@ -31,7 +31,7 @@ public class AsterixInlineVariablesRule extends InlineVariablesRule {
         doNotInlineFuncs.add(AsterixBuiltinFunctions.FIELD_ACCESS_BY_INDEX);
         doNotInlineFuncs.add(AsterixBuiltinFunctions.CLOSED_RECORD_CONSTRUCTOR);
         doNotInlineFuncs.add(AsterixBuiltinFunctions.OPEN_RECORD_CONSTRUCTOR);
-        doNotInlineFuncs.add(AsterixBuiltinFunctions.CAST_RECORD);
+        doNotInlineFuncs.add(AsterixBuiltinFunctions.CAST_TYPE);
         doNotInlineFuncs.add(AsterixBuiltinFunctions.CREATE_CIRCLE);
         doNotInlineFuncs.add(AsterixBuiltinFunctions.CREATE_LINE);
         doNotInlineFuncs.add(AsterixBuiltinFunctions.CREATE_MBR);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java
index b29f110..9d9dda0 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java
@@ -83,13 +83,13 @@ public class ConstantFoldingRule implements IAlgebraicRewriteRule {
 
     // Function Identifier sets that the ConstantFolding rule should skip to apply.
     // Most of them are record-related functions.
-    private static final ImmutableSet<FunctionIdentifier> FUNC_ID_SET_THAT_SHOULD_NOT_BE_APPLIED = ImmutableSet.of(
-            AsterixBuiltinFunctions.RECORD_MERGE, AsterixBuiltinFunctions.ADD_FIELDS,
-            AsterixBuiltinFunctions.REMOVE_FIELDS, AsterixBuiltinFunctions.GET_RECORD_FIELDS,
-            AsterixBuiltinFunctions.GET_RECORD_FIELD_VALUE, AsterixBuiltinFunctions.FIELD_ACCESS_NESTED,
-            AsterixBuiltinFunctions.GET_ITEM, AsterixBuiltinFunctions.OPEN_RECORD_CONSTRUCTOR,
-            AsterixBuiltinFunctions.FIELD_ACCESS_BY_INDEX, AsterixBuiltinFunctions.CAST_RECORD,
-            AsterixBuiltinFunctions.CAST_LIST, AsterixBuiltinFunctions.META, AsterixBuiltinFunctions.META_KEY);
+    private static final ImmutableSet<FunctionIdentifier> FUNC_ID_SET_THAT_SHOULD_NOT_BE_APPLIED =
+            ImmutableSet.of(AsterixBuiltinFunctions.RECORD_MERGE, AsterixBuiltinFunctions.ADD_FIELDS,
+                    AsterixBuiltinFunctions.REMOVE_FIELDS, AsterixBuiltinFunctions.GET_RECORD_FIELDS,
+                    AsterixBuiltinFunctions.GET_RECORD_FIELD_VALUE, AsterixBuiltinFunctions.FIELD_ACCESS_NESTED,
+                    AsterixBuiltinFunctions.GET_ITEM, AsterixBuiltinFunctions.OPEN_RECORD_CONSTRUCTOR,
+                    AsterixBuiltinFunctions.FIELD_ACCESS_BY_INDEX, AsterixBuiltinFunctions.CAST_TYPE,
+                    AsterixBuiltinFunctions.META, AsterixBuiltinFunctions.META_KEY);
 
     /** Throws exceptions in substituiteProducedVariable, setVarType, and one getVarType method. */
     private static final IVariableTypeEnvironment _emptyTypeEnv = new IVariableTypeEnvironment() {
@@ -204,8 +204,9 @@ public class ConstantFoldingRule implements IAlgebraicRewriteRule {
             }
             if (expr.getFunctionIdentifier().equals(AsterixBuiltinFunctions.FIELD_ACCESS_BY_NAME)) {
                 ARecordType rt = (ARecordType) _emptyTypeEnv.getType(expr.getArguments().get(0).getValue());
-                String str = ((AString) ((AsterixConstantValue) ((ConstantExpression) expr.getArguments().get(1)
-                        .getValue()).getValue()).getObject()).getStringValue();
+                String str =
+                        ((AString) ((AsterixConstantValue) ((ConstantExpression) expr.getArguments().get(1).getValue())
+                                .getValue()).getObject()).getStringValue();
                 int k = rt.getFieldIndex(str);
                 if (k >= 0) {
                     // wait for the ByNameToByIndex rule to apply

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IfElseToSwitchCaseFunctionRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IfElseToSwitchCaseFunctionRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IfElseToSwitchCaseFunctionRule.java
deleted file mode 100644
index 76d4a47..0000000
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IfElseToSwitchCaseFunctionRule.java
+++ /dev/null
@@ -1,130 +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.optimizer.rules;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.asterix.lang.common.util.FunctionUtil;
-import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
-import org.apache.commons.lang3.mutable.Mutable;
-import org.apache.commons.lang3.mutable.MutableObject;
-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.ILogicalOperator;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
-import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
-import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
-import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
-import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.SubplanOperator;
-import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
-
-public class IfElseToSwitchCaseFunctionRule implements IAlgebraicRewriteRule {
-
-    @Override
-    public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
-            throws AlgebricksException {
-        return false;
-    }
-
-    @Override
-    public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
-            throws AlgebricksException {
-        AbstractLogicalOperator op1 = (AbstractLogicalOperator) opRef.getValue();
-        if (op1.getOperatorTag() != LogicalOperatorTag.ASSIGN)
-            return false;
-
-        AssignOperator assignOp = (AssignOperator) op1;
-        List<Mutable<ILogicalExpression>> assignExprs = assignOp.getExpressions();
-        if (assignExprs.size() > 1)
-            return false;
-        ILogicalExpression expr = assignExprs.get(0).getValue();
-        if (expr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
-            AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
-            if (!funcExpr.getFunctionIdentifier().equals(AsterixBuiltinFunctions.CONCAT_NON_NULL))
-                return false;
-        }
-
-        AbstractLogicalOperator op2 = (AbstractLogicalOperator) op1.getInputs().get(0).getValue();
-        if (op2.getOperatorTag() != LogicalOperatorTag.SUBPLAN)
-            return false;
-
-        SubplanOperator subplan = (SubplanOperator) op2;
-        List<ILogicalPlan> subPlans = subplan.getNestedPlans();
-        List<Mutable<ILogicalExpression>> arguments = new ArrayList<Mutable<ILogicalExpression>>();
-        for (ILogicalPlan plan : subPlans) {
-            List<Mutable<ILogicalOperator>> roots = plan.getRoots();
-
-            AbstractLogicalOperator nestedRoot = (AbstractLogicalOperator) roots.get(0).getValue();
-            if (nestedRoot.getOperatorTag() != LogicalOperatorTag.SELECT)
-                return false;
-            SelectOperator selectOp = (SelectOperator) nestedRoot;
-
-            AbstractLogicalOperator nestedNextOp = (AbstractLogicalOperator) nestedRoot.getInputs().get(0).getValue();
-            if (nestedNextOp.getOperatorTag() != LogicalOperatorTag.ASSIGN)
-                return false;
-            AssignOperator assignRoot = (AssignOperator) nestedNextOp;
-            Mutable<ILogicalExpression> actionExprRef = assignRoot.getExpressions().get(0);
-
-            arguments.add(selectOp.getCondition());
-            arguments.add(actionExprRef);
-            AbstractLogicalOperator nestedBottomOp = (AbstractLogicalOperator) assignRoot.getInputs().get(0).getValue();
-
-            if (nestedBottomOp.getOperatorTag() != LogicalOperatorTag.NESTEDTUPLESOURCE)
-                return false;
-        }
-
-        AbstractLogicalOperator op3 = (AbstractLogicalOperator) op2.getInputs().get(0).getValue();
-        if (op3.getOperatorTag() != LogicalOperatorTag.ASSIGN)
-            return false;
-
-        AssignOperator bottomAssign = (AssignOperator) op3;
-        LogicalVariable conditionVar = bottomAssign.getVariables().get(0);
-        Mutable<ILogicalExpression> switchCondition = new MutableObject<ILogicalExpression>(
-                new VariableReferenceExpression(conditionVar));
-        List<Mutable<ILogicalExpression>> argumentRefs = new ArrayList<Mutable<ILogicalExpression>>();
-        argumentRefs.add(switchCondition);
-        argumentRefs.addAll(arguments);
-
-        /** replace the branch conditions */
-        for (int i = 0; i < arguments.size(); i += 2) {
-            if (arguments.get(i).getValue().equals(switchCondition.getValue())) {
-                arguments.get(i).setValue(ConstantExpression.TRUE);
-            } else {
-                arguments.get(i).setValue(ConstantExpression.FALSE);
-            }
-        }
-
-        ILogicalExpression callExpr = new ScalarFunctionCallExpression(
-                FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.SWITCH_CASE), argumentRefs);
-
-        assignOp.getInputs().get(0).setValue(op3);
-        assignOp.getExpressions().get(0).setValue(callExpr);
-        context.computeAndSetTypeEnvironmentForOperator(assignOp);
-        return true;
-    }
-}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectToAnyTypeCastRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectToAnyTypeCastRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectToAnyTypeCastRule.java
new file mode 100644
index 0000000..075c1f0
--- /dev/null
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectToAnyTypeCastRule.java
@@ -0,0 +1,145 @@
+/*
+ * 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.optimizer.rules;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.asterix.lang.common.util.FunctionUtil;
+import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
+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.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.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
+import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
+import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
+import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
+
+/**
+ * This rule injects cast functions for "THEN" and "ELSE" branches of a switch-case function if
+ * different "THEN" and "ELSE" branches have heterogeneous return types.
+ */
+public class InjectToAnyTypeCastRule implements IAlgebraicRewriteRule {
+
+    @Override
+    public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
+            throws AlgebricksException {
+        ILogicalOperator op = opRef.getValue();
+        if (op.getInputs().isEmpty()) {
+            return false;
+        }
+        // Populates the latest type information.
+        context.computeAndSetTypeEnvironmentForOperator(op);
+        if (op.acceptExpressionTransform(exprRef -> injectToAnyTypeCast(op, exprRef, context))) {
+            // Generates the up-to-date type information.
+            context.computeAndSetTypeEnvironmentForOperator(op);
+            return true;
+        }
+        return false;
+    }
+
+    // Injects type casts to cast return expressions' return types to ANY.
+    private boolean injectToAnyTypeCast(ILogicalOperator op, Mutable<ILogicalExpression> exprRef,
+            IOptimizationContext context) throws AlgebricksException {
+        ILogicalExpression expr = exprRef.getValue();
+        if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
+            return false;
+        }
+        boolean rewritten = false;
+        AbstractFunctionCallExpression func = (AbstractFunctionCallExpression) expr;
+        for (Mutable<ILogicalExpression> argRef : func.getArguments()) {
+            // Recursively rewrites arguments.
+            if (injectToAnyTypeCast(op, argRef, context)) {
+                context.computeAndSetTypeEnvironmentForOperator(op);
+                rewritten = true;
+            }
+        }
+        if (!func.getFunctionIdentifier().equals(AsterixBuiltinFunctions.SWITCH_CASE)) {
+            return rewritten;
+        }
+        return rewriteSwitchCase(op, func, context);
+    }
+
+    // Injects casts that cast types to ANY for different "THEN" and "ELSE" branches.
+    private boolean rewriteSwitchCase(ILogicalOperator op, AbstractFunctionCallExpression func,
+            IOptimizationContext context) throws AlgebricksException {
+        IVariableTypeEnvironment env = context.getOutputTypeEnvironment(op.getInputs().get(0).getValue());
+        if (!this.isHeterogenous(func, env)) {
+            return false;
+        }
+        List<Mutable<ILogicalExpression>> argRefs = func.getArguments();
+        int argSize = argRefs.size();
+        boolean rewritten = false;
+        for (int argIndex = 2; argIndex < argSize; argIndex += (argIndex + 2 == argSize) ? 1 : 2) {
+            Mutable<ILogicalExpression> argRef = argRefs.get(argIndex);
+            IAType type = (IAType) env.getType(argRefs.get(argIndex).getValue());
+            ATypeTag tag = type.getTypeTag();
+            // Casts are only needed when the original return type is a complex type.
+            // (In the runtime, there is already a type tag for scalar types.)
+            if (tag == ATypeTag.RECORD || tag == ATypeTag.UNORDEREDLIST || tag == ATypeTag.ORDEREDLIST) {
+                ILogicalExpression argExpr = argRef.getValue();
+                // Injects a cast call to cast the data type to ANY.
+                ScalarFunctionCallExpression castFunc = new ScalarFunctionCallExpression(
+                        FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.CAST_TYPE),
+                        new ArrayList<>(Collections.singletonList(new MutableObject<>(argExpr))));
+                TypeCastUtils.setRequiredAndInputTypes(castFunc, BuiltinType.ANY, type);
+                argRef.setValue(castFunc);
+                rewritten = true;
+            }
+        }
+        return rewritten;
+    }
+
+    // Checks whether "THEN" and "ELSE" branches return the heterogeneous types.
+    private boolean isHeterogenous(AbstractFunctionCallExpression func, IVariableTypeEnvironment env)
+            throws AlgebricksException {
+        List<Mutable<ILogicalExpression>> argRefs = func.getArguments();
+        int argSize = argRefs.size();
+        IAType currentType = null;
+        boolean heterogenous = false;
+        for (int argIndex = 2; argIndex < argSize; argIndex += (argIndex + 2 == argSize) ? 1 : 2) {
+            IAType type = (IAType) env.getType(argRefs.get(argIndex).getValue());
+            ATypeTag typeTag = type.getTypeTag();
+            // Null and missing are not considered as heterogeneous with other types.
+            if (typeTag != ATypeTag.NULL && typeTag != ATypeTag.MISSING) {
+                if (typeTag == ATypeTag.UNION) {
+                    type = ((AUnionType) type).getActualType();
+                }
+                if (currentType != null && !type.equals(currentType)) {
+                    heterogenous = true;
+                    break;
+                }
+                currentType = type;
+            }
+        }
+        return heterogenous;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java
index 0fb5b0b..946ec39 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java
@@ -22,14 +22,13 @@ package org.apache.asterix.optimizer.rules;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.commons.lang3.mutable.Mutable;
-
 import org.apache.asterix.metadata.functions.AsterixExternalScalarFunctionInfo;
 import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
 import org.apache.asterix.om.types.ARecordType;
 import org.apache.asterix.om.types.AUnionType;
 import org.apache.asterix.om.types.IAType;
 import org.apache.asterix.om.util.NonTaggedFormatUtil;
+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.base.ILogicalOperator;
@@ -52,7 +51,8 @@ import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
 public class IntroduceDynamicTypeCastForExternalFunctionRule implements IAlgebraicRewriteRule {
 
     @Override
-    public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
+    public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
+            throws AlgebricksException {
         return false;
     }
 
@@ -64,17 +64,21 @@ public class IntroduceDynamicTypeCastForExternalFunctionRule implements IAlgebra
          * resulting plan: distribute_result - project - assign (external function call) - assign (cast-record) - assign(open_record_constructor)
          */
         AbstractLogicalOperator op1 = (AbstractLogicalOperator) opRef.getValue();
-        if (op1.getOperatorTag() != LogicalOperatorTag.DISTRIBUTE_RESULT)
+        if (op1.getOperatorTag() != LogicalOperatorTag.DISTRIBUTE_RESULT) {
             return false;
+        }
         AbstractLogicalOperator op2 = (AbstractLogicalOperator) op1.getInputs().get(0).getValue();
-        if (op2.getOperatorTag() != LogicalOperatorTag.PROJECT)
+        if (op2.getOperatorTag() != LogicalOperatorTag.PROJECT) {
             return false;
+        }
         AbstractLogicalOperator op3 = (AbstractLogicalOperator) op2.getInputs().get(0).getValue();
-        if (op3.getOperatorTag() != LogicalOperatorTag.ASSIGN)
+        if (op3.getOperatorTag() != LogicalOperatorTag.ASSIGN) {
             return false;
+        }
         AbstractLogicalOperator op4 = (AbstractLogicalOperator) op3.getInputs().get(0).getValue();
-        if (op4.getOperatorTag() != LogicalOperatorTag.ASSIGN)
+        if (op4.getOperatorTag() != LogicalOperatorTag.ASSIGN) {
             return false;
+        }
 
         // Op1 : assign (external function call), Op2 : assign (open_record_constructor)
         AssignOperator assignOp1 = (AssignOperator) op3;
@@ -84,8 +88,8 @@ public class IntroduceDynamicTypeCastForExternalFunctionRule implements IAlgebra
         FunctionIdentifier fid = null;
         ILogicalExpression assignExpr = assignOp2.getExpressions().get(0).getValue();
         if (assignExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
-            ScalarFunctionCallExpression funcExpr = (ScalarFunctionCallExpression) assignOp2.getExpressions().get(0)
-                    .getValue();
+            ScalarFunctionCallExpression funcExpr =
+                    (ScalarFunctionCallExpression) assignOp2.getExpressions().get(0).getValue();
             fid = funcExpr.getFunctionIdentifier();
 
             if (fid != AsterixBuiltinFunctions.OPEN_RECORD_CONSTRUCTOR) {
@@ -137,7 +141,7 @@ public class IntroduceDynamicTypeCastForExternalFunctionRule implements IAlgebra
         }
         if (cast) {
             IntroduceDynamicTypeCastRule.addWrapperFunction(requiredRecordType, recordVar.get(0), assignOp1, context,
-                    AsterixBuiltinFunctions.CAST_RECORD);
+                    AsterixBuiltinFunctions.CAST_TYPE);
         }
         return cast || checkUnknown;
     }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java
index e692678..f6cd015 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java
@@ -173,7 +173,7 @@ public class IntroduceDynamicTypeCastRule implements IAlgebraicRewriteRule {
                     AsterixBuiltinFunctions.CHECK_UNKNOWN);
         }
         if (cast) {
-            addWrapperFunction(requiredRecordType, recordVar, op, context, AsterixBuiltinFunctions.CAST_RECORD);
+            addWrapperFunction(requiredRecordType, recordVar, op, context, AsterixBuiltinFunctions.CAST_TYPE);
         }
         return cast || checkUnknown;
     }
@@ -210,15 +210,15 @@ public class IntroduceDynamicTypeCastRule implements IAlgebraicRewriteRule {
                 if (var.equals(recordVar)) {
                     /** insert an assign operator to call the function on-top-of the variable */
                     IAType actualType = (IAType) env.getVarType(var);
-                    AbstractFunctionCallExpression cast = new ScalarFunctionCallExpression(
-                            FunctionUtil.getFunctionInfo(fd));
+                    AbstractFunctionCallExpression cast =
+                            new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(fd));
                     cast.getArguments()
                             .add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(var)));
                     /** enforce the required record type */
                     TypeCastUtils.setRequiredAndInputTypes(cast, requiredRecordType, actualType);
                     LogicalVariable newAssignVar = context.newVar();
-                    AssignOperator newAssignOperator = new AssignOperator(newAssignVar,
-                            new MutableObject<ILogicalExpression>(cast));
+                    AssignOperator newAssignOperator =
+                            new AssignOperator(newAssignVar, new MutableObject<ILogicalExpression>(cast));
                     newAssignOperator.getInputs().add(new MutableObject<ILogicalOperator>(op));
                     opRef.setValue(newAssignOperator);
                     context.computeAndSetTypeEnvironmentForOperator(newAssignOperator);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
index ae69093..c64258f 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
@@ -255,7 +255,7 @@ public class IntroduceSecondaryIndexInsertDeleteRule implements IAlgebraicRewrit
                     context.addNotToBeInlinedVar(castedRecVar);
                     //introduce casting to enforced type
                     AbstractFunctionCallExpression castFunc = new ScalarFunctionCallExpression(
-                            FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.CAST_RECORD));
+                            FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.CAST_TYPE));
                     // The first argument is the record
                     castFunc.getArguments()
                             .add(new MutableObject<ILogicalExpression>(insertOp.getPayloadExpression().getValue()));

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java
index eaf9484..eac35cd 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java
@@ -49,7 +49,6 @@ import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCa
 import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
 import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
-import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
 
 /**
@@ -455,24 +454,25 @@ public class StaticTypeCastUtil {
         if (argExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL
                 || argExpr.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
             IAType reqFieldType = inputFieldType;
-            FunctionIdentifier fi = null;
             // do not enforce nested type in the case of no-used variables
             switch (inputFieldType.getTypeTag()) {
                 case RECORD:
                     reqFieldType = DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE;
-                    fi = AsterixBuiltinFunctions.CAST_RECORD;
                     break;
                 case ORDEREDLIST:
                     reqFieldType = DefaultOpenFieldType.NESTED_OPEN_AORDERED_LIST_TYPE;
-                    fi = AsterixBuiltinFunctions.CAST_LIST;
                     break;
                 case UNORDEREDLIST:
                     reqFieldType = DefaultOpenFieldType.NESTED_OPEN_AUNORDERED_LIST_TYPE;
-                    fi = AsterixBuiltinFunctions.CAST_LIST;
+                    break;
+                default:
+                    break;
             }
-            if (fi != null && !inputFieldType.equals(reqFieldType) && parameterVars.size() > 0) {
+            // do not enforce nested type in the case of no-used variables
+            if (!inputFieldType.equals(reqFieldType) && !parameterVars.isEmpty()) {
                 //inject dynamic type casting
-                injectCastFunction(FunctionUtil.getFunctionInfo(fi), reqFieldType, inputFieldType, expRef, argExpr);
+                injectCastFunction(FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.CAST_TYPE), reqFieldType,
+                        inputFieldType, expRef, argExpr);
                 castInjected = true;
             }
             //recursively rewrite function arguments

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
index 1894cc3..136dd5e 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
@@ -870,9 +870,9 @@ class LangExpressionToPlanTranslator
                 new MutableObject<>(new VariableReferenceExpression(varCond)), ifexpr.getThenExpr());
 
         // Creates a subplan for the "else" branch.
-        AbstractFunctionCallExpression notVarCond =
-                new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(AlgebricksBuiltinFunctions.NOT),
-                        Collections.singletonList(new MutableObject<>(new VariableReferenceExpression(varCond))));
+        AbstractFunctionCallExpression notVarCond = new ScalarFunctionCallExpression(
+                FunctionUtil.getFunctionInfo(AlgebricksBuiltinFunctions.NOT),
+                Collections.singletonList(generateAndNotIsUnknownWrap(new VariableReferenceExpression(varCond))));
         Pair<ILogicalOperator, LogicalVariable> opAndVarForElse = constructSubplanOperatorForBranch(
                 opAndVarForThen.first, new MutableObject<>(notVarCond), ifexpr.getElseExpr());
 
@@ -882,7 +882,6 @@ class LangExpressionToPlanTranslator
         arguments.add(new MutableObject<>(new VariableReferenceExpression(varCond)));
         arguments.add(new MutableObject<>(ConstantExpression.TRUE));
         arguments.add(new MutableObject<>(new VariableReferenceExpression(opAndVarForThen.second)));
-        arguments.add(new MutableObject<>(ConstantExpression.FALSE));
         arguments.add(new MutableObject<>(new VariableReferenceExpression(opAndVarForElse.second)));
         AbstractFunctionCallExpression swithCaseExpr = new ScalarFunctionCallExpression(
                 FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.SWITCH_CASE), arguments);
@@ -1364,10 +1363,14 @@ class LangExpressionToPlanTranslator
 
     protected boolean expressionNeedsNoNesting(Expression expr) {
         Kind k = expr.getKind();
-        return k == Kind.LITERAL_EXPRESSION || k == Kind.LIST_CONSTRUCTOR_EXPRESSION
-                || k == Kind.RECORD_CONSTRUCTOR_EXPRESSION || k == Kind.VARIABLE_EXPRESSION || k == Kind.CALL_EXPRESSION
-                || k == Kind.OP_EXPRESSION || k == Kind.FIELD_ACCESSOR_EXPRESSION || k == Kind.INDEX_ACCESSOR_EXPRESSION
-                || k == Kind.UNARY_EXPRESSION || k == Kind.IF_EXPRESSION || k == Kind.INDEPENDENT_SUBQUERY;
+        boolean noNesting = k == Kind.LITERAL_EXPRESSION || k == Kind.LIST_CONSTRUCTOR_EXPRESSION
+                || k == Kind.RECORD_CONSTRUCTOR_EXPRESSION || k == Kind.VARIABLE_EXPRESSION;
+        noNesting = noNesting || k == Kind.CALL_EXPRESSION || k == Kind.OP_EXPRESSION
+                || k == Kind.FIELD_ACCESSOR_EXPRESSION;
+        noNesting = noNesting || k == Kind.INDEX_ACCESSOR_EXPRESSION || k == Kind.UNARY_EXPRESSION
+                || k == Kind.IF_EXPRESSION;
+        return noNesting || k == Kind.INDEPENDENT_SUBQUERY || k == Kind.CASE_EXPRESSION;
+
     }
 
     protected <T> List<T> mkSingletonArrayList(T item) {
@@ -1519,7 +1522,7 @@ class LangExpressionToPlanTranslator
      * @return a pair of the constructed subplan operator and the output variable for the branch.
      * @throws AsterixException
      */
-    private Pair<ILogicalOperator, LogicalVariable> constructSubplanOperatorForBranch(ILogicalOperator inputOp,
+    protected Pair<ILogicalOperator, LogicalVariable> constructSubplanOperatorForBranch(ILogicalOperator inputOp,
             Mutable<ILogicalExpression> selectExpr, Expression branchExpression) throws AsterixException {
         context.enterSubplan();
         SubplanOperator subplanOp = new SubplanOperator();
@@ -1555,4 +1558,34 @@ class LangExpressionToPlanTranslator
                 .add(new MutableObject<>(new ConstantExpression(new AsterixConstantValue(new AInt64(0L)))));
         return new AssignOperator(v1, new MutableObject<>(comparison));
     }
+
+    // Generates the filter condition for whether a conditional branch should be executed.
+    protected Mutable<ILogicalExpression> generateNoMatchedPrecedingWhenBranchesFilter(
+            List<ILogicalExpression> inputBooleanExprs) {
+        List<Mutable<ILogicalExpression>> arguments = new ArrayList<>();
+        for (ILogicalExpression inputBooleanExpr : inputBooleanExprs) {
+            // A NULL/MISSING valued WHEN expression does not lead to the corresponding THEN execution.
+            // Therefore, we should check a previous WHEN boolean condition is not unknown.
+            arguments.add(generateAndNotIsUnknownWrap(inputBooleanExpr));
+        }
+        Mutable<ILogicalExpression> hasBeenExecutedExprRef = new MutableObject<>(
+                new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.OR), arguments));
+        return new MutableObject<>(
+                new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.NOT),
+                        new ArrayList<>(Collections.singletonList(hasBeenExecutedExprRef))));
+    }
+
+    // For an input expression `expr`, return `expr AND expr IS NOT UNKOWN`.
+    protected Mutable<ILogicalExpression> generateAndNotIsUnknownWrap(ILogicalExpression logicalExpr) {
+        List<Mutable<ILogicalExpression>> arguments = new ArrayList<>();
+        arguments.add(new MutableObject<>(logicalExpr));
+        Mutable<ILogicalExpression> expr = new MutableObject<>(
+                new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.IS_UNKOWN),
+                        new ArrayList<>(Collections.singletonList(new MutableObject<>(logicalExpr)))));
+        arguments.add(new MutableObject<>(
+                new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.NOT),
+                        new ArrayList<>(Collections.singletonList(expr)))));
+        return new MutableObject<>(
+                new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.AND), arguments));
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
index b7ed988..e40de4b 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
@@ -20,6 +20,7 @@ package org.apache.asterix.translator;
 
 import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Deque;
 import java.util.List;
 
@@ -51,12 +52,14 @@ import org.apache.asterix.lang.sqlpp.clause.SelectElement;
 import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
 import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
 import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
 import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.optype.JoinType;
 import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
 import org.apache.asterix.lang.sqlpp.visitor.base.ISqlppVisitor;
 import org.apache.asterix.metadata.declared.AqlMetadataProvider;
+import org.apache.asterix.om.base.ABoolean;
 import org.apache.asterix.om.base.AInt32;
 import org.apache.asterix.om.base.AString;
 import org.apache.asterix.om.constants.AsterixConstantValue;
@@ -72,9 +75,11 @@ import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
+import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.AggregateFunctionCallExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.UnnestingFunctionCallExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractUnnestNonMapOperator;
@@ -142,8 +147,8 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
                 currentOpRef = new MutableObject<>(letClause.accept(this, currentOpRef).first);
             }
         }
-        Pair<ILogicalOperator, LogicalVariable> select = selectExpression.getSelectSetOperation().accept(this,
-                currentOpRef);
+        Pair<ILogicalOperator, LogicalVariable> select =
+                selectExpression.getSelectSetOperation().accept(this, currentOpRef);
         currentOpRef = new MutableObject<>(select.first);
         if (selectExpression.hasOrderby()) {
             currentOpRef = new MutableObject<>(selectExpression.getOrderbyClause().accept(this, currentOpRef).first);
@@ -151,8 +156,8 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
         if (selectExpression.hasLimit()) {
             currentOpRef = new MutableObject<>(selectExpression.getLimitClause().accept(this, currentOpRef).first);
         }
-        Pair<ILogicalOperator, LogicalVariable> result = produceSelectPlan(selectExpression.isSubquery(), currentOpRef,
-                select.second);
+        Pair<ILogicalOperator, LogicalVariable> result =
+                produceSelectPlan(selectExpression.isSubquery(), currentOpRef, select.second);
         if (selectExpression.isSubquery()) {
             context.exitSubplan();
         }
@@ -162,8 +167,8 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
     @Override
     public Pair<ILogicalOperator, LogicalVariable> visit(IndependentSubquery independentSubquery,
             Mutable<ILogicalOperator> tupleSource) throws AsterixException {
-        Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo = langExprToAlgExpression(independentSubquery.getExpr(),
-                tupleSource);
+        Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo =
+                langExprToAlgExpression(independentSubquery.getExpr(), tupleSource);
         // Replaces nested tuple source with empty tuple source so that the subquery can be independent
         // from its input operators.
         replaceNtsWithEts(eo.second.getValue());
@@ -177,8 +182,8 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
     public Pair<ILogicalOperator, LogicalVariable> visit(SelectSetOperation selectSetOperation,
             Mutable<ILogicalOperator> tupSource) throws AsterixException {
         Mutable<ILogicalOperator> currentOpRef = tupSource;
-        Pair<ILogicalOperator, LogicalVariable> currentResult = selectSetOperation.getLeftInput().accept(this,
-                currentOpRef);
+        Pair<ILogicalOperator, LogicalVariable> currentResult =
+                selectSetOperation.getLeftInput().accept(this, currentOpRef);
         if (selectSetOperation.hasRightInputs()) {
             throw new NotImplementedException();
         }
@@ -236,12 +241,12 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
         if (fromTerm.hasPositionalVariable()) {
             LogicalVariable pVar = context.newVar(fromTerm.getPositionalVariable());
             // We set the positional variable type as INT64 type.
-            unnestOp = new UnnestOperator(fromVar,
-                    new MutableObject<ILogicalExpression>(makeUnnestExpression(eo.first)), pVar, BuiltinType.AINT64,
-                    new AqlPositionWriter());
+            unnestOp =
+                    new UnnestOperator(fromVar, new MutableObject<ILogicalExpression>(makeUnnestExpression(eo.first)),
+                            pVar, BuiltinType.AINT64, new AqlPositionWriter());
         } else {
-            unnestOp = new UnnestOperator(fromVar,
-                    new MutableObject<ILogicalExpression>(makeUnnestExpression(eo.first)));
+            unnestOp =
+                    new UnnestOperator(fromVar, new MutableObject<ILogicalExpression>(makeUnnestExpression(eo.first)));
         }
         unnestOp.getInputs().add(eo.second);
 
@@ -267,41 +272,41 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
             throws AsterixException {
         Mutable<ILogicalOperator> leftInputRef = uncorrelatedLeftBranchStack.pop();
         if (joinClause.getJoinType() == JoinType.INNER) {
-            Pair<ILogicalOperator, LogicalVariable> rightBranch = generateUnnestForBinaryCorrelateRightBranch(
-                    joinClause, inputRef, true);
+            Pair<ILogicalOperator, LogicalVariable> rightBranch =
+                    generateUnnestForBinaryCorrelateRightBranch(joinClause, inputRef, true);
             // A join operator with condition TRUE.
-            AbstractBinaryJoinOperator joinOperator = new InnerJoinOperator(
-                    new MutableObject<ILogicalExpression>(ConstantExpression.TRUE), leftInputRef,
-                    new MutableObject<ILogicalOperator>(rightBranch.first));
+            AbstractBinaryJoinOperator joinOperator =
+                    new InnerJoinOperator(new MutableObject<ILogicalExpression>(ConstantExpression.TRUE), leftInputRef,
+                            new MutableObject<ILogicalOperator>(rightBranch.first));
             Mutable<ILogicalOperator> joinOpRef = new MutableObject<>(joinOperator);
 
             // Add an additional filter operator.
-            Pair<ILogicalExpression, Mutable<ILogicalOperator>> conditionExprOpPair = langExprToAlgExpression(
-                    joinClause.getConditionExpression(), joinOpRef);
-            SelectOperator filter = new SelectOperator(new MutableObject<ILogicalExpression>(conditionExprOpPair.first),
-                    false, null);
+            Pair<ILogicalExpression, Mutable<ILogicalOperator>> conditionExprOpPair =
+                    langExprToAlgExpression(joinClause.getConditionExpression(), joinOpRef);
+            SelectOperator filter =
+                    new SelectOperator(new MutableObject<ILogicalExpression>(conditionExprOpPair.first), false, null);
             filter.getInputs().add(conditionExprOpPair.second);
             return new Pair<>(filter, rightBranch.second);
         } else {
             // Creates a subplan operator.
             SubplanOperator subplanOp = new SubplanOperator();
-            Mutable<ILogicalOperator> ntsRef = new MutableObject<>(
-                    new NestedTupleSourceOperator(new MutableObject<ILogicalOperator>(subplanOp)));
+            Mutable<ILogicalOperator> ntsRef =
+                    new MutableObject<>(new NestedTupleSourceOperator(new MutableObject<ILogicalOperator>(subplanOp)));
             subplanOp.getInputs().add(leftInputRef);
 
             // Enters the translation for a subplan.
             context.enterSubplan();
 
             // Adds an unnest operator to unnest to right expression.
-            Pair<ILogicalOperator, LogicalVariable> rightBranch = generateUnnestForBinaryCorrelateRightBranch(
-                    joinClause, ntsRef, true);
+            Pair<ILogicalOperator, LogicalVariable> rightBranch =
+                    generateUnnestForBinaryCorrelateRightBranch(joinClause, ntsRef, true);
             AbstractUnnestNonMapOperator rightUnnestOp = (AbstractUnnestNonMapOperator) rightBranch.first;
 
             // Adds an additional filter operator for the join condition.
             Pair<ILogicalExpression, Mutable<ILogicalOperator>> conditionExprOpPair = langExprToAlgExpression(
                     joinClause.getConditionExpression(), new MutableObject<ILogicalOperator>(rightUnnestOp));
-            SelectOperator filter = new SelectOperator(new MutableObject<ILogicalExpression>(conditionExprOpPair.first),
-                    false, null);
+            SelectOperator filter =
+                    new SelectOperator(new MutableObject<ILogicalExpression>(conditionExprOpPair.first), false, null);
             filter.getInputs().add(conditionExprOpPair.second);
 
             ILogicalOperator currentTopOp = filter;
@@ -327,8 +332,8 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
 
                 // Assigns the record constructor function to a record variable.
                 LogicalVariable recordVar = context.newVar();
-                AssignOperator assignOp = new AssignOperator(recordVar,
-                        new MutableObject<ILogicalExpression>(recordCreationFunc));
+                AssignOperator assignOp =
+                        new AssignOperator(recordVar, new MutableObject<ILogicalExpression>(recordCreationFunc));
                 assignOp.getInputs().add(new MutableObject<ILogicalOperator>(currentTopOp));
 
                 // Sets currentTopOp and varToListify for later usages.
@@ -357,8 +362,8 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
 
             // Outer unnest the aggregated var from the subplan.
             LogicalVariable outerUnnestVar = context.newVar();
-            LeftOuterUnnestOperator outerUnnestOp = new LeftOuterUnnestOperator(outerUnnestVar,
-                    new MutableObject<ILogicalExpression>(
+            LeftOuterUnnestOperator outerUnnestOp =
+                    new LeftOuterUnnestOperator(outerUnnestVar, new MutableObject<ILogicalExpression>(
                             makeUnnestExpression(new VariableReferenceExpression(aggVar))));
             outerUnnestOp.getInputs().add(new MutableObject<ILogicalOperator>(subplanOp));
             currentTopOp = outerUnnestOp;
@@ -423,8 +428,8 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
     @Override
     public Pair<ILogicalOperator, LogicalVariable> visit(HavingClause havingClause, Mutable<ILogicalOperator> tupSource)
             throws AsterixException {
-        Pair<ILogicalExpression, Mutable<ILogicalOperator>> p = langExprToAlgExpression(
-                havingClause.getFilterExpression(), tupSource);
+        Pair<ILogicalExpression, Mutable<ILogicalOperator>> p =
+                langExprToAlgExpression(havingClause.getFilterExpression(), tupSource);
         SelectOperator s = new SelectOperator(new MutableObject<ILogicalExpression>(p.first), false, null);
         s.getInputs().add(p.second);
         return new Pair<>(s, null);
@@ -477,6 +482,86 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
         throw new UnsupportedOperationException(ERR_MSG);
     }
 
+    @Override
+    public Pair<ILogicalOperator, LogicalVariable> visit(CaseExpression caseExpression,
+            Mutable<ILogicalOperator> tupSource) throws AsterixException {
+        //Creates a series of subplan operators, one for each branch.
+        Mutable<ILogicalOperator> currentOpRef = tupSource;
+        ILogicalOperator currentOperator = null;
+        List<Expression> whenExprList = caseExpression.getWhenExprs();
+        List<Expression> thenExprList = caseExpression.getThenExprs();
+        List<ILogicalExpression> branchCondVarReferences = new ArrayList<>();
+        List<ILogicalExpression> allVarReferences = new ArrayList<>();
+        for (int index = 0; index < whenExprList.size(); ++index) {
+            Pair<ILogicalOperator, LogicalVariable> whenExprResult = whenExprList.get(index).accept(this, currentOpRef);
+            currentOperator = whenExprResult.first;
+            // Variable whenConditionVar is corresponds to the current "WHEN" condition.
+            LogicalVariable whenConditionVar = whenExprResult.second;
+            Mutable<ILogicalExpression> branchEntraceConditionExprRef =
+                    new MutableObject<>(new VariableReferenceExpression(whenConditionVar));
+
+            // Constructs an expression that filters data based on preceding "WHEN" conditions
+            // and the current "WHEN" condition. Note that only one "THEN" expression can be run
+            // even though multiple "WHEN" conditions can be satisfied.
+            if (!branchCondVarReferences.isEmpty()) {
+                // The additional filter generated here makes sure the the tuple has not
+                // entered other matched "WHEN...THEN" case.
+                List<Mutable<ILogicalExpression>> andArgs = new ArrayList<>();
+                andArgs.add(generateNoMatchedPrecedingWhenBranchesFilter(branchCondVarReferences));
+                andArgs.add(branchEntraceConditionExprRef);
+
+                // A "THEN" branch can be entered only when the tuple has not enter any other preceding
+                // branches and the current "WHEN" condition is TRUE.
+                branchEntraceConditionExprRef = new MutableObject<>(new ScalarFunctionCallExpression(
+                        FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.AND), andArgs));
+            }
+
+            // Translates the corresponding "THEN" expression.
+            Pair<ILogicalOperator, LogicalVariable> opAndVarForThen = constructSubplanOperatorForBranch(currentOperator,
+                    branchEntraceConditionExprRef, thenExprList.get(index));
+
+            branchCondVarReferences.add(new VariableReferenceExpression(whenConditionVar));
+            allVarReferences.add(new VariableReferenceExpression(whenConditionVar));
+            allVarReferences.add(new VariableReferenceExpression(opAndVarForThen.second));
+            currentOperator = opAndVarForThen.first;
+            currentOpRef = new MutableObject<>(currentOperator);
+        }
+
+        // Creates a subplan for the "ELSE" branch.
+        Mutable<ILogicalExpression> elseCondExprRef =
+                generateNoMatchedPrecedingWhenBranchesFilter(branchCondVarReferences);
+        Pair<ILogicalOperator, LogicalVariable> opAndVarForElse =
+                constructSubplanOperatorForBranch(currentOperator, elseCondExprRef, caseExpression.getElseExpr());
+
+        // Uses switch-case function to select the results of two branches.
+        LogicalVariable selectVar = context.newVar();
+        List<Mutable<ILogicalExpression>> arguments = new ArrayList<>();
+        arguments.add(new MutableObject<>(new ConstantExpression(new AsterixConstantValue(ABoolean.TRUE))));
+        for (ILogicalExpression argVar : allVarReferences) {
+            arguments.add(new MutableObject<>(argVar));
+        }
+        arguments.add(new MutableObject<>(new VariableReferenceExpression(opAndVarForElse.second)));
+        AbstractFunctionCallExpression swithCaseExpr = new ScalarFunctionCallExpression(
+                FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.SWITCH_CASE), arguments);
+        AssignOperator assignOp = new AssignOperator(selectVar, new MutableObject<>(swithCaseExpr));
+        assignOp.getInputs().add(new MutableObject<>(opAndVarForElse.first));
+
+        // Unnests the selected (a "THEN" or "ELSE" branch) result.
+        LogicalVariable unnestVar = context.newVar();
+        UnnestOperator unnestOp = new UnnestOperator(unnestVar,
+                new MutableObject<>(new UnnestingFunctionCallExpression(
+                        FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.SCAN_COLLECTION), Collections
+                                .singletonList(new MutableObject<>(new VariableReferenceExpression(selectVar))))));
+        unnestOp.getInputs().add(new MutableObject<>(assignOp));
+
+        // Produces the final assign operator.
+        LogicalVariable resultVar = context.newVar();
+        AssignOperator finalAssignOp =
+                new AssignOperator(resultVar, new MutableObject<>(new VariableReferenceExpression(unnestVar)));
+        finalAssignOp.getInputs().add(new MutableObject<>(unnestOp));
+        return new Pair<>(finalAssignOp, resultVar);
+    }
+
     private Pair<ILogicalOperator, LogicalVariable> produceSelectPlan(boolean isSubquery,
             Mutable<ILogicalOperator> returnOpRef, LogicalVariable resVar) {
         if (isSubquery) {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java
index 24ddaf6..2c0aef4 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java
@@ -131,8 +131,7 @@ import org.apache.asterix.runtime.evaluators.constructors.ClosedRecordConstructo
 import org.apache.asterix.runtime.evaluators.constructors.OpenRecordConstructorDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.AndDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.AnyCollectionMemberDescriptor;
-import org.apache.asterix.runtime.evaluators.functions.CastListDescriptor;
-import org.apache.asterix.runtime.evaluators.functions.CastRecordDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.CastTypeDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.CheckUnknownDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.CodePointToStringDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.CountHashedGramTokensDescriptor;
@@ -374,10 +373,8 @@ public class FunctionCollection {
         temp.add(OrderedListConstructorDescriptor.FACTORY);
         temp.add(UnorderedListConstructorDescriptor.FACTORY);
 
-        // Cast functions
+        // Inject failure function
         temp.add(InjectFailureDescriptor.FACTORY);
-        temp.add(CastListDescriptor.FACTORY);
-        temp.add(CastRecordDescriptor.FACTORY);
 
         // Switch case
         temp.add(SwitchCaseDescriptor.FACTORY);
@@ -612,6 +609,9 @@ public class FunctionCollection {
         functionsToInjectUnkownHandling.add(GetOverlappingIntervalDescriptor.FACTORY);
         functionsToInjectUnkownHandling.add(DurationFromIntervalDescriptor.FACTORY);
 
+        // Cast function
+        functionsToInjectUnkownHandling.add(CastTypeDescriptor.FACTORY);
+
         List<IFunctionDescriptorFactory> generatedFactories = new ArrayList<>();
         for (IFunctionDescriptorFactory factory : functionsToInjectUnkownHandling) {
             generatedFactories

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryBTreeOperationsHelper.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryBTreeOperationsHelper.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryBTreeOperationsHelper.java
index 15ea2f8..9e2e0b0 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryBTreeOperationsHelper.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryBTreeOperationsHelper.java
@@ -95,8 +95,8 @@ public class SecondaryBTreeOperationsHelper extends SecondaryIndexOperationsHelp
                     secondaryComparatorFactories, secondaryBloomFilterKeyFields, false, dataset.getDatasetId(),
                     mergePolicyFactory, mergePolicyFactoryProperties, filterTypeTraits, filterCmpFactories,
                     secondaryBTreeFields, secondaryFilterFields);
-            localResourceFactoryProvider = new PersistentLocalResourceFactoryProvider(localResourceMetadata,
-                    LocalResource.LSMBTreeResource);
+            localResourceFactoryProvider =
+                    new PersistentLocalResourceFactoryProvider(localResourceMetadata, LocalResource.LSMBTreeResource);
             indexDataflowHelperFactory = new LSMBTreeDataflowHelperFactory(
                     new AsterixVirtualBufferCacheProvider(dataset.getDatasetId()), mergePolicyFactory,
                     mergePolicyFactoryProperties, new SecondaryIndexOperationTrackerProvider(dataset.getDatasetId()),
@@ -146,12 +146,12 @@ public class SecondaryBTreeOperationsHelper extends SecondaryIndexOperationsHelp
 
             // Assign op.
             AbstractOperatorDescriptor sourceOp = primaryScanOp;
-            if (isEnforcingKeyTypes) {
+            if (isEnforcingKeyTypes && !enforcedItemType.equals(itemType)) {
                 sourceOp = createCastOp(spec, dataset.getDatasetType());
                 spec.connect(new OneToOneConnectorDescriptor(spec), primaryScanOp, 0, sourceOp, 0);
             }
-            AlgebricksMetaOperatorDescriptor asterixAssignOp = createExternalAssignOp(spec, numSecondaryKeys,
-                    secondaryRecDesc);
+            AlgebricksMetaOperatorDescriptor asterixAssignOp =
+                    createExternalAssignOp(spec, numSecondaryKeys, secondaryRecDesc);
 
             // If any of the secondary fields are nullable, then add a select op that filters nulls.
             AlgebricksMetaOperatorDescriptor selectOp = null;
@@ -165,13 +165,13 @@ public class SecondaryBTreeOperationsHelper extends SecondaryIndexOperationsHelp
             AsterixStorageProperties storageProperties = propertiesProvider.getStorageProperties();
             // Create secondary BTree bulk load op.
             AbstractTreeIndexOperatorDescriptor secondaryBulkLoadOp;
-            ExternalBTreeWithBuddyDataflowHelperFactory dataflowHelperFactory = new ExternalBTreeWithBuddyDataflowHelperFactory(
-                    mergePolicyFactory, mergePolicyFactoryProperties,
-                    new SecondaryIndexOperationTrackerProvider(dataset.getDatasetId()),
-                    AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER,
-                    LSMBTreeWithBuddyIOOperationCallbackFactory.INSTANCE,
-                    storageProperties.getBloomFilterFalsePositiveRate(), new int[] { numSecondaryKeys },
-                    ExternalDatasetsRegistry.INSTANCE.getDatasetVersion(dataset), true);
+            ExternalBTreeWithBuddyDataflowHelperFactory dataflowHelperFactory =
+                    new ExternalBTreeWithBuddyDataflowHelperFactory(mergePolicyFactory, mergePolicyFactoryProperties,
+                            new SecondaryIndexOperationTrackerProvider(dataset.getDatasetId()),
+                            AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER,
+                            LSMBTreeWithBuddyIOOperationCallbackFactory.INSTANCE,
+                            storageProperties.getBloomFilterFalsePositiveRate(), new int[] { numSecondaryKeys },
+                            ExternalDatasetsRegistry.INSTANCE.getDatasetVersion(dataset), true);
             IOperatorDescriptor root;
             if (externalFiles != null) {
                 // Transaction load
@@ -208,12 +208,12 @@ public class SecondaryBTreeOperationsHelper extends SecondaryIndexOperationsHelp
 
             // Assign op.
             AbstractOperatorDescriptor sourceOp = primaryScanOp;
-            if (isEnforcingKeyTypes) {
+            if (isEnforcingKeyTypes && !enforcedItemType.equals(itemType)) {
                 sourceOp = createCastOp(spec, dataset.getDatasetType());
                 spec.connect(new OneToOneConnectorDescriptor(spec), primaryScanOp, 0, sourceOp, 0);
             }
-            AlgebricksMetaOperatorDescriptor asterixAssignOp = createAssignOp(spec, sourceOp, numSecondaryKeys,
-                    secondaryRecDesc);
+            AlgebricksMetaOperatorDescriptor asterixAssignOp =
+                    createAssignOp(spec, sourceOp, numSecondaryKeys, secondaryRecDesc);
 
             // If any of the secondary fields are nullable, then add a select op that filters nulls.
             AlgebricksMetaOperatorDescriptor selectOp = null;
@@ -311,17 +311,17 @@ public class SecondaryBTreeOperationsHelper extends SecondaryIndexOperationsHelp
         secondaryFieldAccessEvalFactories = new IScalarEvaluatorFactory[numSecondaryKeys + numFilterFields];
         secondaryComparatorFactories = new IBinaryComparatorFactory[numSecondaryKeys + numPrimaryKeys];
         secondaryBloomFilterKeyFields = new int[numSecondaryKeys];
-        ISerializerDeserializer[] secondaryRecFields = new ISerializerDeserializer[numPrimaryKeys + numSecondaryKeys
-                + numFilterFields];
-        ISerializerDeserializer[] enforcedRecFields = new ISerializerDeserializer[1 + numPrimaryKeys
-                + (dataset.hasMetaPart() ? 1 : 0) + numFilterFields];
-        ITypeTraits[] enforcedTypeTraits = new ITypeTraits[1 + numPrimaryKeys + (dataset.hasMetaPart() ? 1 : 0)
-                + numFilterFields];
+        ISerializerDeserializer[] secondaryRecFields =
+                new ISerializerDeserializer[numPrimaryKeys + numSecondaryKeys + numFilterFields];
+        ISerializerDeserializer[] enforcedRecFields =
+                new ISerializerDeserializer[1 + numPrimaryKeys + (dataset.hasMetaPart() ? 1 : 0) + numFilterFields];
+        ITypeTraits[] enforcedTypeTraits =
+                new ITypeTraits[1 + numPrimaryKeys + (dataset.hasMetaPart() ? 1 : 0) + numFilterFields];
         secondaryTypeTraits = new ITypeTraits[numSecondaryKeys + numPrimaryKeys];
         ISerializerDeserializerProvider serdeProvider = metadataProvider.getFormat().getSerdeProvider();
         ITypeTraitProvider typeTraitProvider = metadataProvider.getFormat().getTypeTraitProvider();
-        IBinaryComparatorFactoryProvider comparatorFactoryProvider = metadataProvider.getFormat()
-                .getBinaryComparatorFactoryProvider();
+        IBinaryComparatorFactoryProvider comparatorFactoryProvider =
+                metadataProvider.getFormat().getBinaryComparatorFactoryProvider();
         // Record column is 0 for external datasets, numPrimaryKeys for internal ones
         int recordColumn = dataset.getDatasetType() == DatasetType.INTERNAL ? numPrimaryKeys : 0;
         for (int i = 0; i < numSecondaryKeys; i++) {
@@ -336,8 +336,8 @@ public class SecondaryBTreeOperationsHelper extends SecondaryIndexOperationsHelp
             }
             secondaryFieldAccessEvalFactories[i] = metadataProvider.getFormat().getFieldAccessEvaluatorFactory(
                     isEnforcingKeyTypes ? enforcedItemType : sourceType, secondaryKeyFields.get(i), sourceColumn);
-            Pair<IAType, Boolean> keyTypePair = Index.getNonNullableOpenFieldType(secondaryKeyTypes.get(i),
-                    secondaryKeyFields.get(i), sourceType);
+            Pair<IAType, Boolean> keyTypePair =
+                    Index.getNonNullableOpenFieldType(secondaryKeyTypes.get(i), secondaryKeyFields.get(i), sourceType);
             IAType keyType = keyTypePair.first;
             anySecondaryKeyIsNullable = anySecondaryKeyIsNullable || keyTypePair.second;
             ISerializerDeserializer keySerde = serdeProvider.getSerializerDeserializer(keyType);
@@ -380,8 +380,8 @@ public class SecondaryBTreeOperationsHelper extends SecondaryIndexOperationsHelp
             ISerializerDeserializer serde = serdeProvider.getSerializerDeserializer(type);
             secondaryRecFields[numPrimaryKeys + numSecondaryKeys] = serde;
             enforcedRecFields[numPrimaryKeys + 1 + (dataset.hasMetaPart() ? 1 : 0)] = serde;
-            enforcedTypeTraits[numPrimaryKeys + 1 + (dataset.hasMetaPart() ? 1 : 0)] = typeTraitProvider
-                    .getTypeTrait(type);
+            enforcedTypeTraits[numPrimaryKeys + 1 + (dataset.hasMetaPart() ? 1 : 0)] =
+                    typeTraitProvider.getTypeTrait(type);
         }
         secondaryRecDesc = new RecordDescriptor(secondaryRecFields, secondaryTypeTraits);
         enforcedRecDesc = new RecordDescriptor(enforcedRecFields, enforcedTypeTraits);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryIndexOperationsHelper.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryIndexOperationsHelper.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryIndexOperationsHelper.java
index e677f54..8ebe246 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryIndexOperationsHelper.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryIndexOperationsHelper.java
@@ -53,7 +53,7 @@ import org.apache.asterix.om.types.ARecordType;
 import org.apache.asterix.om.types.IAType;
 import org.apache.asterix.om.util.AsterixAppContextInfo;
 import org.apache.asterix.runtime.evaluators.functions.AndDescriptor;
-import org.apache.asterix.runtime.evaluators.functions.CastRecordDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.CastTypeDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.IsUnknownDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.NotDescriptor;
 import org.apache.asterix.runtime.job.listener.JobEventListenerFactory;
@@ -173,8 +173,8 @@ public abstract class SecondaryIndexOperationsHelper {
             case SINGLE_PARTITION_NGRAM_INVIX:
             case LENGTH_PARTITIONED_WORD_INVIX:
             case LENGTH_PARTITIONED_NGRAM_INVIX: {
-                indexOperationsHelper = new SecondaryInvertedIndexOperationsHelper(physOptConf,
-                        asterixPropertiesProvider);
+                indexOperationsHelper =
+                        new SecondaryInvertedIndexOperationsHelper(physOptConf, asterixPropertiesProvider);
                 break;
             }
             default: {
@@ -240,8 +240,8 @@ public abstract class SecondaryIndexOperationsHelper {
         setSecondaryRecDescAndComparators(indexType, secondaryKeyFields, secondaryKeyTypes, gramLength,
                 metadataProvider);
         numElementsHint = metadataProvider.getCardinalityPerPartitionHint(dataset);
-        Pair<ILSMMergePolicyFactory, Map<String, String>> compactionInfo = DatasetUtils.getMergePolicyFactory(dataset,
-                metadataProvider.getMetadataTxnContext());
+        Pair<ILSMMergePolicyFactory, Map<String, String>> compactionInfo =
+                DatasetUtils.getMergePolicyFactory(dataset, metadataProvider.getMetadataTxnContext());
         mergePolicyFactory = compactionInfo.first;
         mergePolicyFactoryProperties = compactionInfo.second;
 
@@ -276,8 +276,8 @@ public abstract class SecondaryIndexOperationsHelper {
     protected void setPrimaryRecDescAndComparators() throws AlgebricksException {
         List<List<String>> partitioningKeys = DatasetUtils.getPartitioningKeys(dataset);
         int numPrimaryKeys = partitioningKeys.size();
-        ISerializerDeserializer[] primaryRecFields = new ISerializerDeserializer[numPrimaryKeys + 1
-                + (dataset.hasMetaPart() ? 1 : 0)];
+        ISerializerDeserializer[] primaryRecFields =
+                new ISerializerDeserializer[numPrimaryKeys + 1 + (dataset.hasMetaPart() ? 1 : 0)];
         ITypeTraits[] primaryTypeTraits = new ITypeTraits[numPrimaryKeys + 1 + (dataset.hasMetaPart() ? 1 : 0)];
         primaryComparatorFactories = new IBinaryComparatorFactory[numPrimaryKeys];
         primaryBloomFilterKeyFields = new int[numPrimaryKeys];
@@ -287,12 +287,12 @@ public abstract class SecondaryIndexOperationsHelper {
             indicators = ((InternalDatasetDetails) dataset.getDatasetDetails()).getKeySourceIndicator();
         }
         for (int i = 0; i < numPrimaryKeys; i++) {
-            IAType keyType = (indicators == null || indicators.get(i) == 0)
-                    ? itemType.getSubFieldType(partitioningKeys.get(i))
-                    : metaType.getSubFieldType(partitioningKeys.get(i));
+            IAType keyType =
+                    (indicators == null || indicators.get(i) == 0) ? itemType.getSubFieldType(partitioningKeys.get(i))
+                            : metaType.getSubFieldType(partitioningKeys.get(i));
             primaryRecFields[i] = serdeProvider.getSerializerDeserializer(keyType);
-            primaryComparatorFactories[i] = AqlBinaryComparatorFactoryProvider.INSTANCE
-                    .getBinaryComparatorFactory(keyType, true);
+            primaryComparatorFactories[i] =
+                    AqlBinaryComparatorFactoryProvider.INSTANCE.getBinaryComparatorFactory(keyType, true);
             primaryTypeTraits[i] = AqlTypeTraitProvider.INSTANCE.getTypeTrait(keyType);
             primaryBloomFilterKeyFields[i] = i;
         }
@@ -398,8 +398,7 @@ public abstract class SecondaryIndexOperationsHelper {
     }
 
     protected AlgebricksMetaOperatorDescriptor createCastOp(JobSpecification spec, DatasetType dsType) {
-        CastRecordDescriptor castFuncDesc = (CastRecordDescriptor) CastRecordDescriptor.FACTORY
-                .createFunctionDescriptor();
+        CastTypeDescriptor castFuncDesc = (CastTypeDescriptor) CastTypeDescriptor.FACTORY.createFunctionDescriptor();
         castFuncDesc.reset(enforcedItemType, itemType);
 
         int[] outColumns = new int[1];
@@ -419,8 +418,8 @@ public abstract class SecondaryIndexOperationsHelper {
         if (dataset.hasMetaPart()) {
             projectionList[numPrimaryKeys + 1] = numPrimaryKeys + 1;
         }
-        IScalarEvaluatorFactory[] castEvalFact = new IScalarEvaluatorFactory[] {
-                new ColumnAccessEvalFactory(recordIdx) };
+        IScalarEvaluatorFactory[] castEvalFact =
+                new IScalarEvaluatorFactory[] { new ColumnAccessEvalFactory(recordIdx) };
         IScalarEvaluatorFactory[] sefs = new IScalarEvaluatorFactory[1];
         sefs[0] = castFuncDesc.createEvaluatorFactory(castEvalFact);
         AssignRuntimeFactory castAssign = new AssignRuntimeFactory(outColumns, sefs, projectionList);
@@ -463,10 +462,10 @@ public abstract class SecondaryIndexOperationsHelper {
         for (int i = 0; i < numSecondaryKeyFields; i++) {
             // Access column i, and apply 'is not null'.
             ColumnAccessEvalFactory columnAccessEvalFactory = new ColumnAccessEvalFactory(i);
-            IScalarEvaluatorFactory isUnknownEvalFactory = isUnknownDesc
-                    .createEvaluatorFactory(new IScalarEvaluatorFactory[] { columnAccessEvalFactory });
-            IScalarEvaluatorFactory notEvalFactory = notDesc
-                    .createEvaluatorFactory(new IScalarEvaluatorFactory[] { isUnknownEvalFactory });
+            IScalarEvaluatorFactory isUnknownEvalFactory =
+                    isUnknownDesc.createEvaluatorFactory(new IScalarEvaluatorFactory[] { columnAccessEvalFactory });
+            IScalarEvaluatorFactory notEvalFactory =
+                    notDesc.createEvaluatorFactory(new IScalarEvaluatorFactory[] { isUnknownEvalFactory });
             andArgsEvalFactories[i] = notEvalFactory;
         }
         IScalarEvaluatorFactory selectCond = null;