Merge remote-tracking branch 'origin/master' into eugenia/web_ui_beta_fixes
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/base/RuleCollections.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/base/RuleCollections.java
index d5169c7..783fbaa 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/base/RuleCollections.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/base/RuleCollections.java
@@ -20,6 +20,7 @@
 
 import edu.uci.ics.asterix.optimizer.rules.AsterixInlineVariablesRule;
 import edu.uci.ics.asterix.optimizer.rules.ByNameToByIndexFieldAccessRule;
+import edu.uci.ics.asterix.optimizer.rules.CheckFilterExpressionTypeRule;
 import edu.uci.ics.asterix.optimizer.rules.ConstantFoldingRule;
 import edu.uci.ics.asterix.optimizer.rules.CountVarToCountOneRule;
 import edu.uci.ics.asterix.optimizer.rules.ExtractDistinctByExpressionsRule;
@@ -103,6 +104,7 @@
         List<IAlgebraicRewriteRule> typeInfer = new LinkedList<IAlgebraicRewriteRule>();
         typeInfer.add(new InlineUnnestFunctionRule());
         typeInfer.add(new InferTypesRule());
+        typeInfer.add(new CheckFilterExpressionTypeRule());
         return typeInfer;
     }
 
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/CheckFilterExpressionTypeRule.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/CheckFilterExpressionTypeRule.java
new file mode 100644
index 0000000..aa57ab9
--- /dev/null
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/CheckFilterExpressionTypeRule.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2009-2013 by The Regents of the University of California
+ * Licensed 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 from
+ * 
+ *     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 edu.uci.ics.asterix.optimizer.rules;
+
+import org.apache.commons.lang3.mutable.Mutable;
+
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.AUnionType;
+import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.asterix.om.util.NonTaggedFormatUtil;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator;
+import edu.uci.ics.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
+import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
+import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
+import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
+import edu.uci.ics.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
+
+/**
+ * This rule is to check if all the filter expression are of the boolean type or a possible (determined
+ * at the runtime) boolean type.
+ * If that is not the case, an exception should be thrown.
+ * 
+ * @author yingyib
+ */
+public class CheckFilterExpressionTypeRule 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 op = (AbstractLogicalOperator) opRef.getValue();
+        if (op.getOperatorTag() != LogicalOperatorTag.SELECT) {
+            return false;
+        }
+        SelectOperator select = (SelectOperator) op;
+        ILogicalExpression condition = select.getCondition().getValue();
+        IVariableTypeEnvironment env = select.computeOutputTypeEnvironment(context);
+        IAType condType = (IAType) env.getType(condition);
+        if (condType.getTypeTag() != ATypeTag.BOOLEAN && condType.getTypeTag() != ATypeTag.ANY
+                && !isPossibleBoolean(condType)) {
+            throw new AlgebricksException("The select condition " + condition.toString()
+                    + " should be of the boolean type.");
+        }
+        return false;
+    }
+
+    /**
+     * Check if the type is optional boolean or not
+     * 
+     * @param type
+     * @return true if it is; false otherwise.
+     */
+    private boolean isPossibleBoolean(IAType type) {
+        while (type.getTypeTag() == ATypeTag.UNION && NonTaggedFormatUtil.isOptionalField((AUnionType) type)) {
+            type = ((AUnionType) type).getUnionList().get(NonTaggedFormatUtil.OPTIONAL_TYPE_INDEX_IN_UNION_LIST);
+            if (type.getTypeTag() == ATypeTag.BOOLEAN || type.getTypeTag() == ATypeTag.ANY) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java
index 1f242b8..e494ef4 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java
@@ -26,7 +26,10 @@
 import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
 import edu.uci.ics.asterix.om.typecomputer.base.TypeComputerUtilities;
 import edu.uci.ics.asterix.om.types.ARecordType;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.AUnionType;
 import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.asterix.om.util.NonTaggedFormatUtil;
 import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
 import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator;
@@ -37,10 +40,10 @@
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
+import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
 import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
 import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.InsertDeleteOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.ProjectOperator;
 import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities;
 import edu.uci.ics.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
 
@@ -88,62 +91,157 @@
         InsertDeleteOperator insertDeleteOp = (InsertDeleteOperator) op2;
         if (insertDeleteOp.getOperation() == InsertDeleteOperator.Kind.DELETE)
             return false;
-        AbstractLogicalOperator op3 = (AbstractLogicalOperator) op2.getInputs().get(0).getValue();
-        if (op3.getOperatorTag() != LogicalOperatorTag.ASSIGN)
-            return false;
 
         InsertDeleteOperator insertDeleteOperator = (InsertDeleteOperator) op2;
-        AssignOperator oldAssignOperator = (AssignOperator) op3;
-
         AqlDataSource dataSource = (AqlDataSource) insertDeleteOperator.getDataSource();
         IAType[] schemaTypes = (IAType[]) dataSource.getSchemaTypes();
         ARecordType requiredRecordType = (ARecordType) schemaTypes[schemaTypes.length - 1];
+        ILogicalExpression expr = insertDeleteOperator.getPayloadExpression().getValue();
+        List<LogicalVariable> payloadVars = new ArrayList<LogicalVariable>();
+        expr.getUsedVariables(payloadVars);
+        LogicalVariable recordVar = payloadVars.get(0);
+        IVariableTypeEnvironment env = insertDeleteOperator.computeOutputTypeEnvironment(context);
+        IAType inputRecordType = (IAType) env.getVarType(recordVar);
 
-        List<LogicalVariable> usedVariables = new ArrayList<LogicalVariable>();
-        VariableUtilities.getUsedVariables(oldAssignOperator, usedVariables);
-        LogicalVariable inputRecordVar;
-        if (usedVariables.size() > 0) {
-            inputRecordVar = usedVariables.get(0);
-        } else {
-            VariableUtilities.getLiveVariables(oldAssignOperator, usedVariables);
-            inputRecordVar = usedVariables.get(0);
+        /** the input record type can be an union type -- for the case when it comes from a subplan or left-outer join */
+        boolean checkNull = false;
+        while (isOptional(inputRecordType)) {
+            /** while-loop for the case there is a nested multi-level union */
+            inputRecordType = ((AUnionType) inputRecordType).getUnionList().get(
+                    NonTaggedFormatUtil.OPTIONAL_TYPE_INDEX_IN_UNION_LIST);
+            checkNull = true;
         }
-        IVariableTypeEnvironment env = oldAssignOperator.computeInputTypeEnvironment(context);
-        IAType inputRecordType = (IAType) env.getVarType(inputRecordVar);
-        boolean needCast = !requiredRecordType.equals(inputRecordType);
-        if (!needCast)
+
+        /** see whether the input record type needs to be casted */
+        boolean cast = !compatible(requiredRecordType, inputRecordType);
+
+        if (checkNull) {
+            recordVar = addWrapperFunction(requiredRecordType, recordVar, insertDeleteOp, context,
+                    AsterixBuiltinFunctions.NOT_NULL);
+        }
+        if (cast) {
+            addWrapperFunction(requiredRecordType, recordVar, insertDeleteOp, context,
+                    AsterixBuiltinFunctions.CAST_RECORD);
+        }
+        return cast || checkNull;
+    }
+
+    /**
+     * Inject a function to wrap a variable when necessary
+     * 
+     * @param requiredRecordType
+     *            the required record type
+     * @param recordVar
+     *            the record variable
+     * @param parent
+     *            the current parent operator to be rewritten
+     * @param context
+     *            the optimization context
+     * @param fd
+     *            the function to be injected
+     * @return true if cast is injected; false otherwise.
+     * @throws AlgebricksException
+     */
+    public LogicalVariable addWrapperFunction(ARecordType requiredRecordType, LogicalVariable recordVar,
+            ILogicalOperator parent, IOptimizationContext context, FunctionIdentifier fd) throws AlgebricksException {
+        List<Mutable<ILogicalOperator>> opRefs = parent.getInputs();
+        for (int index = 0; index < opRefs.size(); index++) {
+            Mutable<ILogicalOperator> opRef = opRefs.get(index);
+            ILogicalOperator op = opRef.getValue();
+
+            /** get produced vars */
+            List<LogicalVariable> producedVars = new ArrayList<LogicalVariable>();
+            VariableUtilities.getProducedVariables(op, producedVars);
+            IVariableTypeEnvironment env = op.computeOutputTypeEnvironment(context);
+            for (int i = 0; i < producedVars.size(); i++) {
+                LogicalVariable var = producedVars.get(i);
+                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(
+                            FunctionUtils.getFunctionInfo(fd));
+                    cast.getArguments()
+                            .add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(var)));
+                    /** enforce the required record type */
+                    TypeComputerUtilities.setRequiredAndInputTypes(cast, requiredRecordType, actualType);
+                    LogicalVariable newAssignVar = context.newVar();
+                    AssignOperator newAssignOperator = new AssignOperator(newAssignVar,
+                            new MutableObject<ILogicalExpression>(cast));
+                    newAssignOperator.getInputs().add(new MutableObject<ILogicalOperator>(op));
+                    opRef.setValue(newAssignOperator);
+                    context.computeAndSetTypeEnvironmentForOperator(newAssignOperator);
+                    newAssignOperator.computeOutputTypeEnvironment(context);
+                    VariableUtilities.substituteVariables(parent, recordVar, newAssignVar, context);
+                    return newAssignVar;
+                }
+            }
+            /** recursive descend to the operator who produced the recordVar */
+            LogicalVariable replacedVar = addWrapperFunction(requiredRecordType, recordVar, op, context, fd);
+            if (replacedVar != null) {
+                /** substitute the recordVar by the replacedVar for operators who uses recordVar */
+                VariableUtilities.substituteVariables(parent, recordVar, replacedVar, context);
+                return replacedVar;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Check whether the required record type and the input type is compatible
+     * 
+     * @param reqType
+     * @param inputType
+     * @return true if compatible; false otherwise
+     * @throws AlgebricksException
+     */
+    private boolean compatible(ARecordType reqType, IAType inputType) throws AlgebricksException {
+        if (inputType.getTypeTag() == ATypeTag.ANY) {
             return false;
+        }
+        if (inputType.getTypeTag() != ATypeTag.RECORD) {
+            throw new AlgebricksException("The input type " + inputType + " is not a valid record type!");
+        }
 
-        // insert
-        // project
-        // assign
-        // assign
-        AbstractFunctionCallExpression cast = new ScalarFunctionCallExpression(
-                FunctionUtils.getFunctionInfo(AsterixBuiltinFunctions.CAST_RECORD));
-        cast.getArguments().add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(inputRecordVar)));
-        TypeComputerUtilities.setRequiredAndInputTypes(cast, requiredRecordType, inputRecordType);
-        LogicalVariable newAssignVar = context.newVar();
-        AssignOperator newAssignOperator = new AssignOperator(newAssignVar, new MutableObject<ILogicalExpression>(cast));
-        newAssignOperator.getInputs().add(new MutableObject<ILogicalOperator>(op3));
+        IAType[] reqTypes = reqType.getFieldTypes();
+        String[] reqFieldNames = reqType.getFieldNames();
+        IAType[] inputTypes = ((ARecordType) inputType).getFieldTypes();
+        String[] inputFieldNames = ((ARecordType) inputType).getFieldNames();
 
-        List<LogicalVariable> projectVariables = new ArrayList<LogicalVariable>();
-        VariableUtilities.getProducedVariables(oldAssignOperator, projectVariables);
-        projectVariables.add(newAssignVar);
-        ProjectOperator projectOperator = new ProjectOperator(projectVariables);
-        projectOperator.getInputs().add(new MutableObject<ILogicalOperator>(newAssignOperator));
-
-        ILogicalExpression payloadExpr = new VariableReferenceExpression(newAssignVar);
-        MutableObject<ILogicalExpression> payloadRef = new MutableObject<ILogicalExpression>(payloadExpr);
-        InsertDeleteOperator newInserDeleteOperator = new InsertDeleteOperator(insertDeleteOperator.getDataSource(),
-                payloadRef, insertDeleteOperator.getPrimaryKeyExpressions(), insertDeleteOperator.getOperation());
-        newInserDeleteOperator.getInputs().add(new MutableObject<ILogicalOperator>(projectOperator));
-        insertDeleteOperator.getInputs().clear();
-        op1.getInputs().get(0).setValue(newInserDeleteOperator);
-
-        context.computeAndSetTypeEnvironmentForOperator(newAssignOperator);
-        context.computeAndSetTypeEnvironmentForOperator(projectOperator);
-        context.computeAndSetTypeEnvironmentForOperator(newInserDeleteOperator);
+        if (reqTypes.length != inputTypes.length) {
+            return false;
+        }
+        for (int i = 0; i < reqTypes.length; i++) {
+            if (!reqFieldNames[i].equals(inputFieldNames[i])) {
+                return false;
+            }
+            IAType reqTypeInside = reqTypes[i];
+            if (isOptional(reqTypes[i])) {
+                reqTypeInside = ((AUnionType) reqTypes[i]).getUnionList().get(
+                        NonTaggedFormatUtil.OPTIONAL_TYPE_INDEX_IN_UNION_LIST);
+            }
+            IAType inputTypeInside = inputTypes[i];
+            if (isOptional(inputTypes[i])) {
+                if (!isOptional(reqTypes[i])) {
+                    /** if the required type is not optional, the two types are incompatible */
+                    return false;
+                }
+                inputTypeInside = ((AUnionType) inputTypes[i]).getUnionList().get(
+                        NonTaggedFormatUtil.OPTIONAL_TYPE_INDEX_IN_UNION_LIST);
+            }
+            if (inputTypeInside.getTypeTag() != ATypeTag.NULL && !reqTypeInside.equals(inputTypeInside)) {
+                return false;
+            }
+        }
         return true;
     }
 
+    /**
+     * Decide whether a type is an optional type
+     * 
+     * @param type
+     * @return true if it is optional; false otherwise
+     */
+    private boolean isOptional(IAType type) {
+        return type.getTypeTag() == ATypeTag.UNION && NonTaggedFormatUtil.isOptionalField((AUnionType) type);
+    }
 }
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java
index 6e3ab37..d6e0f42 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java
@@ -189,8 +189,7 @@
         if (TypeComputerUtilities.getRequiredType(funcExpr) != null)
             return false;
         TypeComputerUtilities.setRequiredAndInputTypes(funcExpr, requiredRecordType, inputRecordType);
-        staticRecordTypeCast(funcExpr, requiredRecordType, inputRecordType, env);
-        return true;
+        return staticRecordTypeCast(funcExpr, requiredRecordType, inputRecordType, env);
     }
 
     /**
@@ -245,7 +244,7 @@
      *            The type environment.
      * @throws AlgebricksException
      */
-    private static void staticRecordTypeCast(AbstractFunctionCallExpression func, ARecordType reqType,
+    private static boolean staticRecordTypeCast(AbstractFunctionCallExpression func, ARecordType reqType,
             ARecordType inputType, IVariableTypeEnvironment env) throws AlgebricksException {
         IAType[] reqFieldTypes = reqType.getFieldTypes();
         String[] reqFieldNames = reqType.getFieldNames();
@@ -341,8 +340,10 @@
                 }
             }
             // the input has extra fields
-            if (!matched && !reqType.isOpen())
-                throw new AlgebricksException("static type mismatch: including an extra closed field " + fieldName);
+            if (!matched && !reqType.isOpen()) {
+                throw new AlgebricksException("static type mismatch: the input record includes an extra closed field "
+                        + fieldName + ":" + fieldType + "! Please check the field name and type.");
+            }
         }
 
         // backward match: match from required to actual
@@ -385,7 +386,14 @@
                 nullFields[i] = true;
             } else {
                 // no matched field in the input for a required closed field
-                throw new AlgebricksException("static type mismatch: miss a required closed field " + reqFieldName);
+                if (inputType.isOpen()) {
+                    //if the input type is open, return false, give that to dynamic type cast to defer the error to the runtime
+                    return false;
+                } else {
+                    throw new AlgebricksException(
+                            "static type mismatch: the input record misses a required closed field " + reqFieldName
+                                    + ":" + reqFieldType + "! Please check the field name and type.");
+                }
             }
         }
 
@@ -472,6 +480,7 @@
                 arguments.add(expRef);
             }
         }
+        return true;
     }
 
     /**
@@ -505,7 +514,7 @@
      *            the input type
      * @return true if the two types are compatiable; false otherwise
      */
-    private static boolean compatible(IAType reqType, IAType inputType) {
+    public static boolean compatible(IAType reqType, IAType inputType) {
         if (reqType.getTypeTag() == ATypeTag.ANY || inputType.getTypeTag() == ATypeTag.ANY) {
             return true;
         }
diff --git a/asterix-app/src/test/resources/AQLTS/queries/createInternalDataSet.aql b/asterix-app/src/test/resources/AQLTS/queries/createInternalDataSet.aql
new file mode 100644
index 0000000..f141e45
--- /dev/null
+++ b/asterix-app/src/test/resources/AQLTS/queries/createInternalDataSet.aql
@@ -0,0 +1,3 @@
+create dataset ds1(someType) primary key id;
+create internal dataset ds2(someType) primary key id;
+
diff --git a/asterix-app/src/test/resources/AQLTS/queries/utf-8.aql b/asterix-app/src/test/resources/AQLTS/queries/utf-8.aql
new file mode 100644
index 0000000..b9c58ea
--- /dev/null
+++ b/asterix-app/src/test/resources/AQLTS/queries/utf-8.aql
@@ -0,0 +1,3 @@
+string-to-codepoint("äöß");
+string-to-codepoint("迎");
+/* currently fails (issue 277) string-to-codepoint("欢")  */
diff --git a/asterix-app/src/test/resources/AQLTS/queries/variables.aql b/asterix-app/src/test/resources/AQLTS/queries/variables.aql
new file mode 100644
index 0000000..57bfa6b
--- /dev/null
+++ b/asterix-app/src/test/resources/AQLTS/queries/variables.aql
@@ -0,0 +1,4 @@
+let $a:=1
+let $b:=1
+return
+  $b-$a
diff --git a/asterix-app/src/test/resources/runtimets/queries/index-selection/inverted-index-ngram-jaccard/inverted-index-ngram-jaccard.4.query.aql b/asterix-app/src/test/resources/runtimets/queries/index-selection/inverted-index-ngram-jaccard/inverted-index-ngram-jaccard.4.query.aql
index 5d9ad67..dc18182 100644
--- a/asterix-app/src/test/resources/runtimets/queries/index-selection/inverted-index-ngram-jaccard/inverted-index-ngram-jaccard.4.query.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/index-selection/inverted-index-ngram-jaccard/inverted-index-ngram-jaccard.4.query.aql
@@ -1,4 +1,5 @@
 use dataverse test;
+set import-private-functions 'true';
 
 for $o in dataset('DBLP')
 let $jacc := similarity-jaccard-check(gram-tokens($o.title, 3, false), gram-tokens("Transactions for Cooperative Environments", 3, false), 0.5f)
diff --git a/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue258/query-issue258.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue258/query-issue258.1.ddl.aql
new file mode 100644
index 0000000..5b219b5
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue258/query-issue258.1.ddl.aql
@@ -0,0 +1,18 @@
+/*
+ * Description  : This test case is to verify the fix for issue258
+ 				: https://code.google.com/p/asterixdb/issues/detail?id=258
+ * Expected Res : Success
+ * Date         : 21 May 2013
+ */
+
+drop dataverse test if exists;
+create dataverse test if not exists;
+use dataverse test;
+
+create type t1 as closed {
+id:int32
+};
+
+
+create dataset ds1(t1) primary key id;
+create dataset ds2(t1) primary key id;
diff --git a/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue258/query-issue258.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue258/query-issue258.2.update.aql
new file mode 100644
index 0000000..fb334ad
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue258/query-issue258.2.update.aql
@@ -0,0 +1,20 @@
+/*
+ * Description  : This test case is to verify the fix for issue258
+ 				: https://code.google.com/p/asterixdb/issues/detail?id=258
+ * Expected Res : Success
+ * Date         : 21 May 2013
+ */
+
+use dataverse test;
+
+insert into dataset ds1(
+let $L:= 
+  for $x in dataset('ds2')
+  where $x.id = 10
+  return $x
+return
+  if (count($L) <= 0) then
+    {"id": 10}
+  else
+    {"id": 5}
+);
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue258/query-issue258.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue258/query-issue258.3.query.aql
new file mode 100644
index 0000000..fff488a
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue258/query-issue258.3.query.aql
@@ -0,0 +1,11 @@
+/*
+ * Description  : This test case is to verify the fix for issue258
+ 				: https://code.google.com/p/asterixdb/issues/detail?id=258
+ * Expected Res : Success
+ * Date         : 21 May 2013
+ */
+
+use dataverse test;
+
+for $d in dataset ds1
+return $d;
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453-2/query-issue453-2.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453-2/query-issue453-2.1.ddl.aql
new file mode 100644
index 0000000..6fcce66
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453-2/query-issue453-2.1.ddl.aql
@@ -0,0 +1,20 @@
+/*
+ * Description  : This test case is to verify the fix for issue453
+ 				: https://code.google.com/p/asterixdb/issues/detail?id=453
+ * Expected Res : SUCCESS
+ * Date         : 18th May 2013
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+use dataverse test;
+
+create type TypeOpen as open {
+    id : int32,
+    int_m : int32,
+    int_o : int32?,
+    string_m : string,
+    string_o : string?
+};
+
+create dataset DataOpen(TypeOpen) primary key id;
diff --git a/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453-2/query-issue453-2.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453-2/query-issue453-2.2.update.aql
new file mode 100644
index 0000000..2682e84
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453-2/query-issue453-2.2.update.aql
@@ -0,0 +1,27 @@
+/*
+ * Description  : This test case is to verify the fix for issue453
+ 				: https://code.google.com/p/asterixdb/issues/detail?id=453
+ * Expected Res : SUCCESS
+ * Date         : 18th May 2013
+ */
+
+use dataverse test;
+
+insert into dataset DataOpen(
+      for $arr at $pos in (
+          for $i1 in [1, 2]
+          for $i2 in [1, null]
+          for $s1 in ["a", "b"]
+          for $s2 in ["a", null]
+          return
+            [ $i1, $i2, $s1, $s2]
+        )
+      return
+          {
+            "id" : $pos,
+            "int_m" : $arr[0], 
+            "int_o" : $arr[1],
+            "string_m" : $arr[2],
+            "string_o" : $arr[3]
+          }
+      )
diff --git a/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453-2/query-issue453-2.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453-2/query-issue453-2.3.query.aql
new file mode 100644
index 0000000..1381365
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453-2/query-issue453-2.3.query.aql
@@ -0,0 +1,12 @@
+/*
+ * Description  : This test case is to verify the fix for issue453
+ 				: https://code.google.com/p/asterixdb/issues/detail?id=453
+ * Expected Res : SUCCESS
+ * Date         : 18th May 2013
+ */
+
+use dataverse test;
+
+for $d in dataset DataOpen
+order by $d.id
+return $d
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453/query-issue453.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453/query-issue453.1.ddl.aql
new file mode 100644
index 0000000..6fcce66
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453/query-issue453.1.ddl.aql
@@ -0,0 +1,20 @@
+/*
+ * Description  : This test case is to verify the fix for issue453
+ 				: https://code.google.com/p/asterixdb/issues/detail?id=453
+ * Expected Res : SUCCESS
+ * Date         : 18th May 2013
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+use dataverse test;
+
+create type TypeOpen as open {
+    id : int32,
+    int_m : int32,
+    int_o : int32?,
+    string_m : string,
+    string_o : string?
+};
+
+create dataset DataOpen(TypeOpen) primary key id;
diff --git a/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453/query-issue453.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453/query-issue453.2.update.aql
new file mode 100644
index 0000000..3346f52
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453/query-issue453.2.update.aql
@@ -0,0 +1,16 @@
+/*
+ * Description  : This test case is to verify the fix for issue453
+ 				: https://code.google.com/p/asterixdb/issues/detail?id=453
+ * Expected Res : SUCCESS
+ * Date         : 18th May 2013
+ */
+
+use dataverse test;
+
+insert into dataset DataOpen(
+      for $o in {{
+          { "id": 0, "int_m": 1, "int_o": 1, "string_m": "a", "string_o": "a" },
+          { "id": 1, "int_m": 1, "int_o": 1, "string_m": "a", "string_o": null }
+        }}
+      return $o
+)
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453/query-issue453.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453/query-issue453.3.query.aql
new file mode 100644
index 0000000..1381365
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/open-closed/query-issue453/query-issue453.3.query.aql
@@ -0,0 +1,12 @@
+/*
+ * Description  : This test case is to verify the fix for issue453
+ 				: https://code.google.com/p/asterixdb/issues/detail?id=453
+ * Expected Res : SUCCESS
+ * Date         : 18th May 2013
+ */
+
+use dataverse test;
+
+for $d in dataset DataOpen
+order by $d.id
+return $d
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/queries/user-defined-functions/udf27/udf27.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/user-defined-functions/udf27/udf27.3.query.aql
index 50a1cb2..fd383cf 100644
--- a/asterix-app/src/test/resources/runtimets/queries/user-defined-functions/udf27/udf27.3.query.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/user-defined-functions/udf27/udf27.3.query.aql
@@ -10,4 +10,4 @@
 use dataverse test;
 
 let $a := true
-return some $i in [100,200] satisfies test.f1()
+return some $i in [100,200] satisfies $i<test.f1()
diff --git a/asterix-app/src/test/resources/runtimets/queries/user-defined-functions/udf30/udf30.1.query.aql b/asterix-app/src/test/resources/runtimets/queries/user-defined-functions/udf30/udf30.1.query.aql
new file mode 100644
index 0000000..ffe6981
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/user-defined-functions/udf30/udf30.1.query.aql
@@ -0,0 +1,14 @@
+/*
+ * Description  : Declare a UDF and try to use the function parameter outside
+ *                of the function.
+ * Expected Res : Failure
+ * Date         : Apr 10th 2013
+ */
+
+declare function abc($y) {
+ let $x:=3
+ return $x
+};
+
+let $z:=$y
+return $z
diff --git a/asterix-app/src/test/resources/runtimets/results/open-closed/query-issue258/query-issue258.1.adm b/asterix-app/src/test/resources/runtimets/results/open-closed/query-issue258/query-issue258.1.adm
new file mode 100644
index 0000000..0e739c3
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/open-closed/query-issue258/query-issue258.1.adm
@@ -0,0 +1 @@
+{ "id": 10 }
diff --git a/asterix-app/src/test/resources/runtimets/results/open-closed/query-issue453-2/query-issue453-2.1.adm b/asterix-app/src/test/resources/runtimets/results/open-closed/query-issue453-2/query-issue453-2.1.adm
new file mode 100644
index 0000000..b573845
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/open-closed/query-issue453-2/query-issue453-2.1.adm
@@ -0,0 +1,16 @@
+{ "id": 0, "int_m": 1, "int_o": 1, "string_m": "a", "string_o": "a" }
+{ "id": 1, "int_m": 1, "int_o": 1, "string_m": "a", "string_o": null }
+{ "id": 2, "int_m": 1, "int_o": 1, "string_m": "b", "string_o": "a" }
+{ "id": 3, "int_m": 1, "int_o": 1, "string_m": "b", "string_o": null }
+{ "id": 4, "int_m": 1, "int_o": null, "string_m": "a", "string_o": "a" }
+{ "id": 5, "int_m": 1, "int_o": null, "string_m": "a", "string_o": null }
+{ "id": 6, "int_m": 1, "int_o": null, "string_m": "b", "string_o": "a" }
+{ "id": 7, "int_m": 1, "int_o": null, "string_m": "b", "string_o": null }
+{ "id": 8, "int_m": 2, "int_o": 1, "string_m": "a", "string_o": "a" }
+{ "id": 9, "int_m": 2, "int_o": 1, "string_m": "a", "string_o": null }
+{ "id": 10, "int_m": 2, "int_o": 1, "string_m": "b", "string_o": "a" }
+{ "id": 11, "int_m": 2, "int_o": 1, "string_m": "b", "string_o": null }
+{ "id": 12, "int_m": 2, "int_o": null, "string_m": "a", "string_o": "a" }
+{ "id": 13, "int_m": 2, "int_o": null, "string_m": "a", "string_o": null }
+{ "id": 14, "int_m": 2, "int_o": null, "string_m": "b", "string_o": "a" }
+{ "id": 15, "int_m": 2, "int_o": null, "string_m": "b", "string_o": null }
diff --git a/asterix-app/src/test/resources/runtimets/results/open-closed/query-issue453/query-issue453.1.adm b/asterix-app/src/test/resources/runtimets/results/open-closed/query-issue453/query-issue453.1.adm
new file mode 100644
index 0000000..c076685
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/open-closed/query-issue453/query-issue453.1.adm
@@ -0,0 +1,2 @@
+{ "id": 0, "int_m": 1, "int_o": 1, "string_m": "a", "string_o": "a" }
+{ "id": 1, "int_m": 1, "int_o": 1, "string_m": "a", "string_o": null }
diff --git a/asterix-app/src/test/resources/runtimets/testsuite.xml b/asterix-app/src/test/resources/runtimets/testsuite.xml
index 18ec161..956c76d 100644
--- a/asterix-app/src/test/resources/runtimets/testsuite.xml
+++ b/asterix-app/src/test/resources/runtimets/testsuite.xml
@@ -1556,7 +1556,6 @@
   </test-group>
   -->
   <test-group name="fuzzyjoin">
-    <!-- internal function
     <test-case FilePath="fuzzyjoin">
       <compilation-unit name="dblp-1_1">
         <output-dir compare="Text">dblp-1_1</output-dir>
@@ -1577,8 +1576,6 @@
         <output-dir compare="Text">dblp-1_2</output-dir>
       </compilation-unit>
     </test-case>
-   -->
-    <!-- internal function
     <test-case FilePath="fuzzyjoin">
       <compilation-unit name="dblp-2.1_5.3.1">
         <output-dir compare="Text">dblp-2.1_5.3.1</output-dir>
@@ -1649,7 +1646,6 @@
         <output-dir compare="Text">dblp-3_1</output-dir>
       </compilation-unit>
     </test-case>
-    -->
     <test-case FilePath="fuzzyjoin">
       <compilation-unit name="dblp-aqlplus_1">
         <output-dir compare="Text">dblp-aqlplus_1</output-dir>
@@ -1661,7 +1657,6 @@
         <expected-error>edu.uci.ics.asterix.common.exceptions.AsterixException</expected-error>
       </compilation-unit>
     </test-case>
-   <!-- internal function
     <test-case FilePath="fuzzyjoin">
       <compilation-unit name="dblp-csx-2_1">
         <output-dir compare="Text">dblp-csx-2_1</output-dir>
@@ -1849,13 +1844,11 @@
         <output-dir compare="Text">fuzzy-inverted-index-ngram-edit-distance</output-dir>
       </compilation-unit>
     </test-case>
-    <!-- internal function
     <test-case FilePath="index-selection">
       <compilation-unit name="fuzzy-inverted-index-ngram-jaccard">
         <output-dir compare="Text">fuzzy-inverted-index-ngram-jaccard</output-dir>
       </compilation-unit>
     </test-case>
-    -->
     <test-case FilePath="index-selection">
       <compilation-unit name="fuzzy-inverted-index-olist-edit-distance-panic">
         <output-dir compare="Text">fuzzy-inverted-index-olist-edit-distance-panic</output-dir>
@@ -1901,13 +1894,11 @@
         <output-dir compare="Text">inverted-index-ngram-edit-distance</output-dir>
       </compilation-unit>
     </test-case>
-    <!-- internal function
     <test-case FilePath="index-selection">
       <compilation-unit name="inverted-index-ngram-jaccard">
         <output-dir compare="Text">inverted-index-ngram-jaccard</output-dir>
       </compilation-unit>
     </test-case>
-    -->
     <test-case FilePath="index-selection">
       <compilation-unit name="inverted-index-olist-edit-distance-panic">
         <output-dir compare="Text">inverted-index-olist-edit-distance-panic</output-dir>
@@ -1995,20 +1986,16 @@
         <output-dir compare="Text">ngram-edit-distance-inline</output-dir>
       </compilation-unit>
     </test-case>
-   <!-- internal function
     <test-case FilePath="inverted-index-join">
       <compilation-unit name="ngram-jaccard">
         <output-dir compare="Text">ngram-jaccard</output-dir>
       </compilation-unit>
     </test-case>
-   -->
-   <!-- internal function
     <test-case FilePath="inverted-index-join">
       <compilation-unit name="ngram-jaccard-inline">
         <output-dir compare="Text">ngram-jaccard-inline</output-dir>
       </compilation-unit>
     </test-case>
-    -->
     <test-case FilePath="inverted-index-join">
       <compilation-unit name="olist-edit-distance">
         <output-dir compare="Text">olist-edit-distance</output-dir>
@@ -2061,7 +2048,6 @@
         <output-dir compare="Text">ngram-edit-distance-inline</output-dir>
       </compilation-unit>
     </test-case>
-   <!-- internal function
     <test-case FilePath="inverted-index-join-noeqjoin">
       <compilation-unit name="ngram-jaccard">
         <output-dir compare="Text">ngram-jaccard</output-dir>
@@ -2072,7 +2058,6 @@
         <output-dir compare="Text">ngram-jaccard-inline</output-dir>
       </compilation-unit>
     </test-case>
-   -->
     <test-case FilePath="inverted-index-join-noeqjoin">
       <compilation-unit name="olist-edit-distance">
         <output-dir compare="Text">olist-edit-distance</output-dir>
@@ -2801,10 +2786,25 @@
     </test-case>
     <test-case FilePath="open-closed">
       <compilation-unit name="query-issue410">
-        <output-dir compare="Text">query-issue40</output-dir>
+        <output-dir compare="Text">query-issue410</output-dir>
         <expected-error>edu.uci.ics.asterix.common.exceptions.AsterixException</expected-error>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="open-closed">
+      <compilation-unit name="query-issue453">
+	<output-dir compare="Text">query-issue453</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="open-closed">
+      <compilation-unit name="query-issue453-2">
+	<output-dir compare="Text">query-issue453-2</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="open-closed">
+      <compilation-unit name="query-issue258">
+        <output-dir compare="Text">query-issue258</output-dir>
+      </compilation-unit>
+    </test-case>
   </test-group>
   <test-group name="quantifiers">
     <test-case FilePath="quantifiers">
@@ -2869,7 +2869,6 @@
     </test-case>
   </test-group>
   <test-group name="records">
-    <!-- internal function
     <test-case FilePath="records">
       <compilation-unit name="closed-record-constructor_01">
         <output-dir compare="Text">closed-record-constructor_01</output-dir>
@@ -2891,19 +2890,16 @@
         <output-dir compare="Text">expFieldName</output-dir>
       </compilation-unit>
     </test-case>
-    <!-- internal function
     <test-case FilePath="records">
       <compilation-unit name="field-access-by-index_01">
         <output-dir compare="Text">field-access-by-index_01</output-dir>
       </compilation-unit>
     </test-case>
-    -->
     <test-case FilePath="records">
       <compilation-unit name="field-access-on-open-field">
         <output-dir compare="Text">field-access-on-open-field</output-dir>
       </compilation-unit>
     </test-case>
-    <!-- internal function
     <test-case FilePath="records">
       <compilation-unit name="open-record-constructor_01">
         <output-dir compare="Text">open-record-constructor_01</output-dir>
@@ -2914,7 +2910,6 @@
         <output-dir compare="Text">open-record-constructor_02</output-dir>
       </compilation-unit>
     </test-case>
-    -->
     <test-case FilePath="records">
       <compilation-unit name="closed-closed-fieldname-conflict_issue173">
         <output-dir compare="Text">closed-closed-fieldname-conflict_issue173</output-dir>
@@ -3034,7 +3029,6 @@
         <output-dir compare="Text">edit-distance-check_strings</output-dir>
       </compilation-unit>
     </test-case>
-   <!-- internal function
     <test-case FilePath="similarity">
       <compilation-unit name="edit-distance-list-is-filterable">
         <output-dir compare="Text">edit-distance-list-is-filterable</output-dir>
@@ -3045,7 +3039,6 @@
         <output-dir compare="Text">edit-distance-string-is-filterable</output-dir>
       </compilation-unit>
     </test-case>
-    -->
     <test-case FilePath="similarity">
       <compilation-unit name="edit-distance_ints">
         <output-dir compare="Text">edit-distance_ints</output-dir>
@@ -3066,13 +3059,11 @@
         <output-dir compare="Text">fuzzyeq-similarity-jaccard</output-dir>
       </compilation-unit>
     </test-case>
-    <!-- internal function
     <test-case FilePath="similarity">
       <compilation-unit name="prefix-len-jaccard">
         <output-dir compare="Text">prefix-len-jaccard</output-dir>
       </compilation-unit>
     </test-case>
-    -->
     <test-case FilePath="similarity">
       <compilation-unit name="similarity-jaccard-check_ints">
         <output-dir compare="Text">similarity-jaccard-check_ints</output-dir>
@@ -3088,7 +3079,6 @@
         <output-dir compare="Text">similarity-jaccard-check_strings</output-dir>
       </compilation-unit>
     </test-case>
-    <!-- internal function
     <test-case FilePath="similarity">
       <compilation-unit name="similarity-jaccard-prefix-check">
         <output-dir compare="Text">similarity-jaccard-prefix-check</output-dir>
@@ -3114,8 +3104,6 @@
         <output-dir compare="Text">similarity-jaccard-sorted-check_strings</output-dir>
       </compilation-unit>
     </test-case>
-    -->
-   <!-- internal functions
     <test-case FilePath="similarity">
       <compilation-unit name="similarity-jaccard-sorted_ints">
         <output-dir compare="Text">similarity-jaccard-sorted_ints</output-dir>
@@ -3146,7 +3134,6 @@
         <output-dir compare="Text">similarity-jaccard_strings</output-dir>
       </compilation-unit>
     </test-case>
-   -->
   </test-group>
   <test-group name="spatial">
     <test-case FilePath="spatial">
@@ -3528,7 +3515,6 @@
         <output-dir compare="Text">string-concat1</output-dir>
       </compilation-unit>
     </test-case>
-   <!-- internal function
     <test-case FilePath="string">
       <compilation-unit name="string-equal1">
         <output-dir compare="Text">string-equal1</output-dir>
@@ -3549,7 +3535,6 @@
         <output-dir compare="Text">string-equal4</output-dir>
       </compilation-unit>
     </test-case>
-   -->
     <test-case FilePath="string">
       <compilation-unit name="string-join1">
         <output-dir compare="Text">string-join1</output-dir>
@@ -3688,7 +3673,6 @@
       </compilation-unit>
     </test-case>
   </test-group>
-  <!-- internal function
   <test-group name="subset-collection">
     <test-case FilePath="subset-collection">
       <compilation-unit name="01">
@@ -3706,11 +3690,6 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="subset-collection">
-      <compilation-unit name="04">
-        <output-dir compare="Text">04</output-dir>
-      </compilation-unit>
-    </test-case>
-    <test-case FilePath="subset-collection">
       <compilation-unit name="05">
         <output-dir compare="Text">05</output-dir>
       </compilation-unit>
@@ -3726,9 +3705,7 @@
       </compilation-unit>
     </test-case>
   </test-group>
-  -->
   <test-group name="tokenizers">
-   <!-- internal function
     <test-case FilePath="tokenizers">
       <compilation-unit name="counthashed-gram-tokens_01">
         <output-dir compare="Text">counthashed-gram-tokens_01</output-dir>
@@ -3744,8 +3721,6 @@
         <output-dir compare="Text">counthashed-word-tokens_01</output-dir>
       </compilation-unit>
     </test-case>
-    -->
-   <!-- internal function
     <test-case FilePath="tokenizers">
       <compilation-unit name="gram-tokens_01">
         <output-dir compare="Text">gram-tokens_01</output-dir>
@@ -3756,8 +3731,6 @@
         <output-dir compare="Text">gram-tokens_02</output-dir>
       </compilation-unit>
     </test-case>
-   -->
-   <!-- internal function
     <test-case FilePath="tokenizers">
       <compilation-unit name="hashed-gram-tokens_01">
         <output-dir compare="Text">hashed-gram-tokens_01</output-dir>
@@ -3773,7 +3746,6 @@
         <output-dir compare="Text">hashed-word-tokens_01</output-dir>
       </compilation-unit>
     </test-case>
-   -->
     <test-case FilePath="tokenizers">
       <compilation-unit name="word-tokens_01">
         <output-dir compare="Text">word-tokens_01</output-dir>
@@ -3846,13 +3818,11 @@
         <output-dir compare="Text">q18_large_volume_customer</output-dir>
       </compilation-unit>
     </test-case>
-    <!-- internal function
     <test-case FilePath="tpch">
       <compilation-unit name="q19_discounted_revenue">
         <output-dir compare="Text">q19_discounted_revenue</output-dir>
       </compilation-unit>
     </test-case>
-    -->
     <test-case FilePath="tpch">
       <compilation-unit name="q1_pricing_summary_report_nt">
         <output-dir compare="Text">q1_pricing_summary_report_nt</output-dir>
@@ -4034,13 +4004,11 @@
     </test-case>
   </test-group>
   <test-group name="user-defined-functions">
-   <!-- internal function
     <test-case FilePath="user-defined-functions">
       <compilation-unit name="query-issue201">
         <output-dir compare="Text">query-issue201</output-dir>
       </compilation-unit>
     </test-case>
-   -->
     <test-case FilePath="user-defined-functions">
       <compilation-unit name="query-issue455">
         <output-dir compare="Text">query-issue455</output-dir>
@@ -4202,6 +4170,12 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="user-defined-functions">
+      <compilation-unit name="udf30">
+        <output-dir compare="Text">udf30</output-dir>
+        <expected-error>edu.uci.ics.asterix.common.exceptions.AsterixException</expected-error>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="user-defined-functions">
       <compilation-unit name="f01">
         <output-dir compare="Text">f01</output-dir>
         <expected-error>edu.uci.ics.asterix.common.exceptions.AsterixException</expected-error> 
@@ -4315,7 +4289,6 @@
         <output-dir compare="Text">adjust_timezone</output-dir>
       </compilation-unit>
   	</test-case>
-       <!-- internal function
   	<test-case FilePath="temporal">
   		<compilation-unit name="calendar_duration">
         <output-dir compare="Text">calendar_duration</output-dir>
@@ -4331,7 +4304,6 @@
         <output-dir compare="Text">datetime_functions</output-dir>
       </compilation-unit>
   	</test-case>
-       -->
         <!--
    	<test-case FilePath="temporal">
            <compilation-unit name="insert_from_delimited_ds">
@@ -4349,25 +4321,21 @@
         <output-dir compare="Text">interval_functions</output-dir>
       </compilation-unit>
   	</test-case>
-        <!-- internal functions
   	<test-case FilePath="temporal">
   		<compilation-unit name="time_functions">
         <output-dir compare="Text">time_functions</output-dir>
       </compilation-unit>
   	</test-case>
-       -->
   	<test-case FilePath="constructor">
   		<compilation-unit name="interval">
         <output-dir compare="Text">interval</output-dir>
       </compilation-unit>
   	</test-case>
-        <!-- internal function
   	<test-case FilePath="temporal">
   		<compilation-unit name="duration_comps">
         <output-dir compare="Text">duration_comps</output-dir>
       </compilation-unit>
   	</test-case>
-       -->
   </test-group>
   <test-group name="leftouterjoin">
     <test-case FilePath="leftouterjoin">
diff --git a/asterix-aql/src/main/javacc/AQL.jj b/asterix-aql/src/main/javacc/AQL.jj
index dc01648..2a5f534 100644
--- a/asterix-aql/src/main/javacc/AQL.jj
+++ b/asterix-aql/src/main/javacc/AQL.jj
@@ -301,7 +301,7 @@
                                    fdd,
                                    ifNotExists);
       }
-    | <DATASET> nameComponents = QualifiedName()
+    | ("internal")? <DATASET> nameComponents = QualifiedName()
     <LEFTPAREN> typeName = Identifier() <RIGHTPAREN>
     ifNotExists = IfNotExists()
     primaryKeyFields = PrimaryKey() ("on" nodeGroupName = Identifier() )?
@@ -420,7 +420,6 @@
   boolean ifNotExists = false;
   List<VarIdentifier> paramList = new ArrayList<VarIdentifier>();
   String functionBody;
-  VarIdentifier var = null;
   Expression functionBodyExpr;
   Token beginPos;
   Token endPos;
@@ -431,6 +430,29 @@
 {
   "function" nameComponents = FunctionOrTypeName()
   ifNotExists = IfNotExists()
+  paramList = ParameterList()
+  "{"
+    {
+      beginPos = token;
+    } 
+  functionBodyExpr = Expression() "}"
+    {
+      endPos = token;
+      functionBody = extractFragment(beginPos.beginLine, beginPos.beginColumn, endPos.beginLine, endPos.beginColumn);
+      String dataverse = nameComponents.first.getValue();
+      String functionName = nameComponents.second.getValue();      
+      signature = new FunctionSignature(dataverse, functionName, paramList.size());
+      getCurrentScope().addFunctionDescriptor(signature, false);
+      return new CreateFunctionStatement(signature, paramList, functionBody, ifNotExists);
+    }
+}
+
+List<VarIdentifier> ParameterList() throws ParseException:
+{
+  List<VarIdentifier> paramList = new ArrayList<VarIdentifier>();
+  VarIdentifier var = null;
+}
+{
   <LEFTPAREN> (<VARIABLE>
     {
       var = new VarIdentifier();
@@ -445,19 +467,9 @@
       paramList.add(var);
       getCurrentScope().addNewVarSymbolToScope(var);
     }
-  )*)? <RIGHTPAREN> "{"
+  )*)? <RIGHTPAREN>
     {
-      beginPos = token;
-    } 
-  functionBodyExpr = Expression() "}"
-    {
-      endPos = token;
-      functionBody = extractFragment(beginPos.beginLine, beginPos.beginColumn, endPos.beginLine, endPos.beginColumn);
-      String dataverse = nameComponents.first.getValue();
-      String functionName = nameComponents.second.getValue();      
-      signature = new FunctionSignature(dataverse, functionName, paramList.size());
-      getCurrentScope().addFunctionDescriptor(signature, false);
-      return new CreateFunctionStatement(signature, paramList, functionBody, ifNotExists);
+      return paramList;
     }
 }
 
@@ -1093,34 +1105,19 @@
   FunctionDecl funcDecl;
   FunctionSignature signature;
   String functionName;
-  int arity = 0;
   List<VarIdentifier> paramList = new ArrayList<VarIdentifier>();
   Expression funcBody;
-  VarIdentifier var = null;
   createNewScope();
 }
 {
-  "declare" "function" functionName = Identifier() <LEFTPAREN> (<VARIABLE>
+  "declare" "function" functionName = Identifier()
+  paramList = ParameterList()
+  "{" funcBody = Expression() "}"
     {
-      var = new VarIdentifier();
-      var.setValue(token.image);
-      paramList.add(var);
-      getCurrentScope().addNewVarSymbolToScope(var);
-      arity++;
-    }
-  ("," <VARIABLE>
-    {
-      var = new VarIdentifier();
-      var.setValue(token.image);
-      paramList.add(var);
-      getCurrentScope().addNewVarSymbolToScope(var);
-      arity++;
-    }
-  )*)? <RIGHTPAREN> "{" funcBody = Expression() "}"
-    {
-      signature = new FunctionSignature(defaultDataverse, functionName, arity);
+      signature = new FunctionSignature(defaultDataverse, functionName, paramList.size());
       getCurrentScope().addFunctionDescriptor(signature, false);
       funcDecl = new FunctionDecl(signature, paramList, funcBody);
+      removeCurrentScope();
       return funcDecl;
     }
 }
@@ -1539,7 +1536,7 @@
 	VarIdentifier var = new VarIdentifier();
 }
 {
-      <VARIABLE>
+  <VARIABLE>
     {
      String varName = token.image; 
      Identifier ident = lookupSymbol(varName);
@@ -1564,7 +1561,7 @@
 	VarIdentifier var = new VarIdentifier();
 }
 {
-      <VARIABLE>
+  <VARIABLE>
     {
      Identifier ident = lookupSymbol(token.image);
      if(ident != null) { // exist such ident
@@ -2204,7 +2201,7 @@
 <DEFAULT>
 TOKEN :
 {
-	<VARIABLE : "$" <IDENTIFIER> >
+	<VARIABLE : "$" (<LETTER>)+ (<LETTER> | <DIGIT> | "_")* >
 }
 
 SKIP:
diff --git a/asterix-doc/src/site/markdown/AsterixAlphaRelease.md b/asterix-doc/src/site/markdown/AsterixAlphaRelease.md
index 1b899ef..ff9efb2 100644
--- a/asterix-doc/src/site/markdown/AsterixAlphaRelease.md
+++ b/asterix-doc/src/site/markdown/AsterixAlphaRelease.md
@@ -11,7 +11,7 @@
 The ASTERIX effort has been targeting a wide range of semi-structured information, ranging from "data" use cases---where information is well-typed and highly regular---to "content" use cases---where data tends to be irregular, much of each datum may be textual, and the ultimate schema for the various data types involved may be hard to anticipate up front.
 The ASTERIX project has been addressing technical issues including highly scalable data storage and indexing, semi-structured query processing on very large clusters, and merging time-tested parallel database techniques with modern data-intensive computing techniques to support performant yet declarative solutions to the problem of storing and analyzing semi-structured information effectively.
 The first fruits of this labor have been captured in the AsterixDB system that is now being released in preliminary or "Alpha" release form.
-We are hoping that the arrival of AsterixDB will mark the beginning of the "BDMS era", and we hope that both the Big Data community and the database community will find the AsterixDB system to be interesting and useful for a much broader class of problems than can be addressed with any one of today's current Big Data platforms and related technologies (e.g., Hadoop, Pig, Hive, HBase, Cassandra, and so on).  One of our project mottos has been "one size fits a bunch"---at least that has been our aim.  For more information about the research effort that led to the birth of AsterixDB, please refer to our NSF project web site: [http://asterix.ics.uci.edu/](http://asterix.ics.uci.edu/).
+We are hoping that the arrival of AsterixDB will mark the beginning of the "BDMS era", and we hope that both the Big Data community and the database community will find the AsterixDB system to be interesting and useful for a much broader class of problems than can be addressed with any one of today's current Big Data platforms and related technologies (e.g., Hadoop, Pig, Hive, HBase, MongoDB, and so on).  One of our project mottos has been "one size fits a bunch"---at least that has been our aim.  For more information about the research effort that led to the birth of AsterixDB, please refer to our NSF project web site: [http://asterix.ics.uci.edu/](http://asterix.ics.uci.edu/).
 
 In a nutshell, AsterixDB is a full-function BDMS with a rich feature set that distinguishes it from pretty much any other Big Data platform that's out and available today.  We believe that its feature set makes it well-suited to modern needs such as web data warehousing and social data storage and analysis.  AsterixDB has:
 
diff --git a/asterix-doc/src/site/markdown/AsterixDataTypes.md b/asterix-doc/src/site/markdown/AsterixDBDataModel.md
similarity index 94%
rename from asterix-doc/src/site/markdown/AsterixDataTypes.md
rename to asterix-doc/src/site/markdown/AsterixDBDataModel.md
index 6674006..ffefd09 100644
--- a/asterix-doc/src/site/markdown/AsterixDataTypes.md
+++ b/asterix-doc/src/site/markdown/AsterixDBDataModel.md
@@ -23,7 +23,12 @@
 
 
 ### Int8 / Int16 / Int32 / Int64 ###
-Integer types using 8, 16, 32, or 64 bits.
+Integer types using 8, 16, 32, or 64 bits. The ranges of these types are:
+
+- `Int8`: -127 to 127
+- `Int16`: -32767 to 32767
+- `Int32`: -2147483647 to 2147483647
+- `Int64`: -9223372036854775808 to 9223372036854775807
 
  * Example:
 
@@ -40,7 +45,7 @@
 
 
 ### Float ###
-`Float` represents approximate numeric data values using 4 bytes.
+`Float` represents approximate numeric data values using 4 bytes. The range of a float value can be from 2^(-149) to (2-2^(-23)·2^(127) for both positive and negative. Beyond these ranges will get `INF` or `-INF`.
 
  * Example:
 
@@ -57,7 +62,7 @@
 
 
 ### Double ###
-`Double` represents approximate numeric data values using 8 bytes.
+`Double` represents approximate numeric data values using 8 bytes. The range of a double value can be from (2^(-1022)) to (2-2^(-52))·2^(1023) for both positive and negative. Beyond these ranges will get `INF` or `-INF`.
 
  * Example:
 
diff --git a/asterix-doc/src/site/markdown/AsterixDataTypesAndFunctions.md b/asterix-doc/src/site/markdown/AsterixDBFunctions.md
similarity index 86%
rename from asterix-doc/src/site/markdown/AsterixDataTypesAndFunctions.md
rename to asterix-doc/src/site/markdown/AsterixDBFunctions.md
index 7576648..d47752c 100644
--- a/asterix-doc/src/site/markdown/AsterixDataTypesAndFunctions.md
+++ b/asterix-doc/src/site/markdown/AsterixDBFunctions.md
@@ -1,290 +1,3 @@
-# Asterix Data Model (ADM) #
-
-# Basic data types #
-
-An instance of Asterix data model (ADM) can be a _primitive type_ (`Int32`, `Int64`, `String`, `Float`, `Double`, `Date`, `Time`, `Datetime`, etc. or `NULL`) or a _derived type_.
-
-## Primitive Types ##
-
-### Boolean ###
-`Boolean` data type can have one of the two values: _*true*_ or _*false*_.
-
- * Example:
-
-        let $t := true
-        let $f := false
-        return { "true": $t, "false": $f }
-
-
- * The expected result is:
-
-        { "true": true, "false": false }
-
-
-
-### Int8 / Int16 / Int32 / Int64 ###
-Integer types using 8, 16, 32, or 64 bits.
-
- * Example:
-
-        let $v8 := int8("125")
-        let $v16 := int16("32765")
-        let $v32 := 294967295
-        let $v64 := int64("1700000000000000000")
-        return { "int8": $v8, "int16": $v16, "int32": $v32, "int64": $v64}
-
-
- * The expected result is:
-
-        { "int8": 125i8, "int16": 32765i16, "int32": 294967295, "int64": 1700000000000000000i64 }
-
-
-### Float ###
-`Float` represents approximate numeric data values using 4 bytes.
-
- * Example:
-
-        let $v1 := float("NaN")
-        let $v2 := float("INF")
-        let $v3 := float("-INF")
-        let $v4 := float("-2013.5")
-        return { "v1": $v1, "v2": $v2, "v3": $v3, "v4": $v4 }
-
-
- * The expected result is:
-
-        { "v1": NaNf, "v2": Infinityf, "v3": -Infinityf, "v4": -2013.5f }
-
-
-### Double ###
-`Double` represents approximate numeric data values using 8 bytes.
-
- * Example:
-
-        let $v1 := double("NaN")
-        let $v2 := double("INF")
-        let $v3 := double("-INF")
-        let $v4 := double("-2013.593823748327284")
-        return { "v1": $v1, "v2": $v2, "v3": $v3, "v4": $v4 }
-
-
- * The expected result is:
-
-        { "v1": NaNd, "v2": Infinityd, "v3": -Infinityd, "v4": -2013.5938237483274d }
-
-
-### String ###
-`String` represents a sequence of characters.
-
- * Example:
-
-        let $v1 := string("This is a string.")
-        let $v2 := string("\"This is a quoted string\"")
-        return { "v1": $v1, "v2": $v2 }
-
-
- * The expected result is:
-
-        { "v1": "This is a string.", "v2": "\"This is a quoted string\"" }
-
-
-### Point ###
-`Point` is the fundamental two-dimensional building block for spatial types. It consists of two `double` coordinates x and y.
-
- * Example:
-
-        let $v1 := point("80.10d, -10E5")
-        let $v2 := point("5.10E-10d, -10E5")
-        return { "v1": $v1, "v2": $v2 }
-
-
- * The expected result is:
-
-        { "v1": point("80.1,-1000000.0"), "v2": point("5.1E-10,-1000000.0") }
-
-
-### Line ###
-`Line` consists of two points that represent the start and the end points of a line segment.
-
- * Example:
-
-        let $v1 := line("10.1234,11.1e-1 +10.2E-2,-11.22")
-        let $v2 := line("0.1234,-1.00e-10 +10.5E-2,-01.02")
-        return { "v1": $v1, "v2": $v2 }
-
-
- * The expected result is:
-
-        { "v1": line("10.1234,1.11 0.102,-11.22"), "v2": line("0.1234,-1.0E-10 0.105,-1.02") }
-
-
-### Rectangle ###
-`Rectangle` consists of two points that represent the _*bottom left*_ and _*upper right*_ corners of a rectangle.
-
- * Example:
-
-        let $v1 := rectangle("5.1,11.8 87.6,15.6548")
-        let $v2 := rectangle("0.1234,-1.00e-10 5.5487,0.48765")
-        return { "v1": $v1, "v2": $v2 }
-
-
- * The expected result is:
-
-        { "v1": rectangle("5.1,11.8 87.6,15.6548"), "v2": rectangle("0.1234,-1.0E-10 5.5487,0.48765") }
-
-
-### Circle ###
-`Circle` consists of one `point` that represents the center of the circle and a radius of type `double`.
-
- * Example:
-
-        let $v1 := circle("10.1234,11.1e-1 +10.2E-2")
-        let $v2 := circle("0.1234,-1.00e-10 +10.5E-2")
-        return { "v1": $v1, "v2": $v2 }
-
-
- * The expected result is:
-
-        { "v1": circle("10.1234,1.11 0.102"), "v2": circle("0.1234,-1.0E-10 0.105") }
-
-
-### Polygon ###
-`Polygon` consists of _*n*_ points that represent the vertices of a _*simple closed*_ polygon.
-
- * Example:
-
-        let $v1 := polygon("-1.2,+1.3e2 -2.14E+5,2.15 -3.5e+2,03.6 -4.6E-3,+4.81")
-        let $v2 := polygon("-1.0,+10.5e2 -02.15E+50,2.5 -1.0,+3.3e3 -2.50E+05,20.15 +3.5e+2,03.6 -4.60E-3,+4.75 -2,+1.0e2 -2.00E+5,20.10 30.5,03.25 -4.33E-3,+4.75")
-        return { "v1": $v1, "v2": $v2 }
-
-
- * The expected result is:
-
-        { "v1": polygon("-1.2,130.0 -214000.0,2.15 -350.0,3.6 -0.0046,4.81"), "v2": polygon("-1.0,1050.0 -2.15E50,2.5 -1.0,3300.0 -250000.0,20.15 350.0,3.6 -0.0046,4.75 -2.0,100.0 -200000.0,20.1 30.5,3.25 -0.00433,4.75") }
-
-
-### Date ###
-`Date` represents a time point along the Gregorian calendar system specified by the year, month and day. ASTERIX supports the date from `-9999-01-01` to `9999-12-31`.
-
-A date value can be represented in two formats, extended format and basic format.
-
- * Extended format is represented as `[-]yyyy-mm-dd` for `year-month-day`. Each field should be padded if there are less digits than the format specified.
- * Basic format is in the format of `[-]yyyymmdd`.
-
- * Example:
-
-        let $v1 := date("2013-01-01")
-        let $v2 := date("-19700101")
-        return { "v1": $v1, "v2": $v2 }
-
-
- * The expected result is:
-
-        { "v1": date("2013-01-01"), "v2": date("-1970-01-01") }
-
-
-### Time ###
-`Time` type describes the time within the range of a day. It is represented by three fields: hour, minute and second. Millisecond field is optional as the fraction of the second field. Its extended format is as `hh:mm:ss[.mmm]` and the basic format is `hhmmss[mmm]`. The value domain is from `00:00:00.000` to `23:59:59.999`.
-
-Timezone field is optional for a time value. Timezone is represented as `[+|-]hh:mm` for extended format or `[+|-]hhmm` for basic format. Note that the sign designators cannot be omitted. `Z` can also be used to represent the UTC local time. If no timezone information is given, it is UTC by default.
-
- * Example:
-
-        let $v1 := time("12:12:12.039Z")
-        let $v2 := time("000000000-0800")
-        return { "v1": $v1, "v2": $v2 }
-
-
- * The expected result is:
-
-        { "v1": time("12:12:12.039Z"), "v2": time("08:00:00.000Z") }
-
-
-### Datetime ###
-A `Datetime` value is a combination of an `Date` and `Time`, representing a fixed time point along the Gregorian calendar system. The value is among `-9999-01-01 00:00:00.000` and `9999-12-31 23:59:59.999`.
-
-A `Datetime` value is represented as a combination of the representation of its `Date` part and `Time` part, separated by a separator `T`. Either extended or basic format can be used, and the two parts should be the same format.
-
-Millisecond field and timezone field are optional, as specified in the `Time` type.
-
- * Example:
-
-        let $v1 := datetime("2013-01-01T12:12:12.039Z")
-        let $v2 := datetime("-19700101T000000000-0800")
-        return { "v1": $v1, "v2": $v2 }
-
-
- * The expected result is:
-
-        { "v1": datetime("2013-01-01T12:12:12.039Z"), "v2": datetime("-1970-01-01T08:00:00.000Z") }
-
-
-### Duration ###
-`Duration` represents a duration of time. A duration value is specified by integers on at least one of the following fields: year, month, day, hour, minute, second, and millisecond.
-
-A duration value is in the format of `[-]PnYnMnDTnHnMn.mmmS`. The millisecond part (as the fraction of the second field) is optional, and when no millisecond field is used, the decimal point should also be absent.
-
-Negative durations are also supported for the arithmetic operations between time instance types (`Date`, `Time` and `Datetime`), and is used to roll the time back for the given duration. For example `date("2012-01-01") + duration("-P3D")` will return `date("2011-12-29")`.
-
-Note that a canonical representation of the duration is always returned, regardless whether the duration is in the canonical representation or not from the user's input. More information about canonical representation can be found from [XPath dayTimeDuration Canonical Representation](http://www.w3.org/TR/xpath-functions/#canonical-dayTimeDuration) and [yearMonthDuration Canonical Representation](http://www.w3.org/TR/xpath-functions/#canonical-yearMonthDuration).
-
- * Example:
-
-        let $v1 := duration("P100Y12MT12M")
-        let $v2 := duration("-PT20.943S")
-        return { "v1": $v1, "v2": $v2 }
-
-
- * The expected result is:
-
-        { "v1": duration("P101YT12M"), "v2": duration("-PT20.943S") }
-
-
-### Interval ###
-`Interval` represents inclusive-exclusive ranges of time. It is defined by two time point values with the same temporal type(`Date`, `Time` or `Datetime`).
-
- * Example:
-
-        let $v1 := interval-from-date(date("2013-01-01"), date("20130505"))
-        let $v2 := interval-from-time(time("00:01:01"), time("213901049+0800"))
-        let $v3 := interval-from-datetime(datetime("2013-01-01T00:01:01"), datetime("20130505T213901049+0800"))
-        return { "v1": $v1, "v2": $v2, "v3": $v3 }
-
-
- * The expected result is:
-
-        { "v1": interval-date("2013-01-01, 2013-05-05"), "v2": interval-time("00:01:01.000Z, 13:39:01.049Z"), "v3": interval-datetime("2013-01-01T00:01:01.000Z, 2013-05-05T13:39:01.049Z") }
-
-
-## Derived Types ##
-
-### Record ###
-A `Record` contains a set of fields, where each field is described by its name and type. A record type is either open or closed. Open records can contain fields that are not part of the type definition, while closed records cannot. Syntactically, record constructors are surrounded by curly braces "{...}".
-
-An example would be
-
-
-        { "id": 213508, "name": "Alice Bob" }
-
-
-### OrderedList ###
-An `OrderedList` is a sequence of values for which the order is determined by creation or insertion. OrderedList constructors are denoted by brackets: "[...]".
-
-An example would be
-
-
-        ["alice", 123, "bob", null]
-
-
-### UnorderedList ###
-An `UnorderedList` is an unordered sequence of values, similar to bags in SQL. UnorderedList constructors are denoted by two opening flower braces followed by data and two closing flower braces, like "{{...}}".
-
-An example would be
-
-
-        {{"hello", 9328, "world", [1, 2, null]}}
-
-
 # Asterix: Using Functions #
 Asterix provides rich support of various classes of functions to support operations on string, spatial, and temporal data.  This document explains how to use these functions.
 
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/builders/RecordBuilder.java b/asterix-om/src/main/java/edu/uci/ics/asterix/builders/RecordBuilder.java
index f5d07ae..10b6071 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/builders/RecordBuilder.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/builders/RecordBuilder.java
@@ -150,7 +150,7 @@
         // +1 because we do not store the value tag.
         closedPartOutputStream.write(value.getByteArray(), value.getStartOffset() + 1, len);
         numberOfClosedFields++;
-        if (isNullable && value.getByteArray()[0] != SER_NULL_TYPE_TAG) {
+        if (isNullable && value.getByteArray()[value.getStartOffset()] != SER_NULL_TYPE_TAG) {
             nullBitMap[id / 8] |= (byte) (1 << (7 - (id % 8)));
         }
     }
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/formats/nontagged/AqlBinaryBooleanInspectorImpl.java b/asterix-om/src/main/java/edu/uci/ics/asterix/formats/nontagged/AqlBinaryBooleanInspectorImpl.java
index 97a0c13..4d85537 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/formats/nontagged/AqlBinaryBooleanInspectorImpl.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/formats/nontagged/AqlBinaryBooleanInspectorImpl.java
@@ -1,6 +1,7 @@
 package edu.uci.ics.asterix.formats.nontagged;
 
 import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.EnumDeserializer;
 import edu.uci.ics.hyracks.algebricks.data.IBinaryBooleanInspector;
 import edu.uci.ics.hyracks.algebricks.data.IBinaryBooleanInspectorFactory;
 import edu.uci.ics.hyracks.api.context.IHyracksTaskContext;
@@ -24,6 +25,11 @@
     public boolean getBooleanValue(byte[] bytes, int offset, int length) {
         if (bytes[offset] == SER_NULL_TYPE_TAG)
             return false;
+        /** check if the runtime type is boolean */
+        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(bytes[offset]);
+        if (typeTag != ATypeTag.BOOLEAN) {
+            throw new IllegalStateException("Runtime error: the select condition should be of the boolean type!");
+        }
         return bytes[offset + 1] == 1;
     }
 
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixBuiltinFunctions.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixBuiltinFunctions.java
index 38af5e1..eb882b8 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixBuiltinFunctions.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixBuiltinFunctions.java
@@ -29,6 +29,7 @@
 import edu.uci.ics.asterix.om.typecomputer.impl.CastListResultTypeComputer;
 import edu.uci.ics.asterix.om.typecomputer.impl.CastRecordResultTypeComputer;
 import edu.uci.ics.asterix.om.typecomputer.impl.ClosedRecordConstructorResultType;
+import edu.uci.ics.asterix.om.typecomputer.impl.ConcatNonNullTypeComputer;
 import edu.uci.ics.asterix.om.typecomputer.impl.FieldAccessByIndexResultType;
 import edu.uci.ics.asterix.om.typecomputer.impl.InjectFailureTypeComputer;
 import edu.uci.ics.asterix.om.typecomputer.impl.NonTaggedCollectionMemberResultType;
@@ -86,7 +87,6 @@
 import edu.uci.ics.asterix.om.types.AbstractCollectionType;
 import edu.uci.ics.asterix.om.types.BuiltinType;
 import edu.uci.ics.asterix.om.types.IAType;
-import edu.uci.ics.asterix.om.types.TypeHelper;
 import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
 import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
@@ -620,22 +620,8 @@
         add(CARET, NonTaggedNumericAddSubMulDivTypeComputer.INSTANCE);
         add(CIRCLE_CONSTRUCTOR, OptionalACircleTypeComputer.INSTANCE);
         add(CLOSED_RECORD_CONSTRUCTOR, ClosedRecordConstructorResultType.INSTANCE);
-        add(CONCAT_NON_NULL, new IResultTypeComputer() {
-            @Override
-            public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env,
-                    IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
-                AbstractFunctionCallExpression f = (AbstractFunctionCallExpression) expression;
-                if (f.getArguments().size() < 1) {
-                    return BuiltinType.ANULL;
-                }
-                ILogicalExpression a0 = f.getArguments().get(0).getValue();
-                IAType t0 = (IAType) env.getType(a0);
-                if (TypeHelper.canBeNull(t0)) {
-                    return t0;
-                }
-                return AUnionType.createNullableType(t0);
-            }
-        });
+        add(CONCAT_NON_NULL, ConcatNonNullTypeComputer.INSTANCE);
+
         add(CONTAINS, ABooleanTypeComputer.INSTANCE);
         add(COUNT, AInt32TypeComputer.INSTANCE);
         add(COUNTHASHED_GRAM_TOKENS, OrderedListOfAInt32TypeComputer.INSTANCE);
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ARecordCaster.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ARecordCaster.java
index 494ea6f..ed9690c 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ARecordCaster.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/pointables/cast/ARecordCaster.java
@@ -99,7 +99,7 @@
             start = bos.size();
             dos.write(ATypeTag.NULL.serialize());
             end = bos.size();
-            nullTypeTag.set(bos.getByteArray(), start, end);
+            nullTypeTag.set(bos.getByteArray(), start, end - start);
         } catch (IOException e) {
             throw new IllegalStateException(e);
         }
@@ -150,7 +150,7 @@
         for (int i = 0; i < optionalFields.length; i++)
             optionalFields[i] = false;
 
-        bos.reset(nullReference.getStartOffset() + nullReference.getLength());
+        bos.reset(nullTypeTag.getStartOffset() + nullTypeTag.getLength());
         for (int i = 0; i < numSchemaFields; i++) {
             ATypeTag ftypeTag = fieldTypes[i].getTypeTag();
             String fname = fieldNames[i];
@@ -278,8 +278,14 @@
             // recursively casting, the result of casting can always be thought
             // as flat
             if (optionalFields[i]) {
-                nestedVisitorArg.second = ((AUnionType) fType).getUnionList().get(
-                        NonTaggedFormatUtil.OPTIONAL_TYPE_INDEX_IN_UNION_LIST);
+                if (fieldTypeTags.size() <= i || fieldTypeTags.get(i) == null
+                        || fieldTypeTags.get(i).equals(nullTypeTag)) {
+                    //the field is optional in the input record
+                    nestedVisitorArg.second = ((AUnionType) fType).getUnionList().get(0);
+                } else {
+                    nestedVisitorArg.second = ((AUnionType) fType).getUnionList().get(
+                            NonTaggedFormatUtil.OPTIONAL_TYPE_INDEX_IN_UNION_LIST);
+                }
             }
             field.accept(visitor, nestedVisitorArg);
             recBuilder.addField(i, nestedVisitorArg.first);
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/impl/ConcatNonNullTypeComputer.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/impl/ConcatNonNullTypeComputer.java
new file mode 100644
index 0000000..7bf2668
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/impl/ConcatNonNullTypeComputer.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2009-2013 by The Regents of the University of California
+ * Licensed 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 from
+ * 
+ *     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 edu.uci.ics.asterix.om.typecomputer.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import edu.uci.ics.asterix.om.typecomputer.base.IResultTypeComputer;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.AUnionType;
+import edu.uci.ics.asterix.om.types.BuiltinType;
+import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
+import edu.uci.ics.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
+
+/**
+ * The type computer for concat-not-null.
+ * Note that this function is only used for the if-then-else clause.
+ * 
+ * @author yingyib
+ */
+public class ConcatNonNullTypeComputer implements IResultTypeComputer {
+
+    public static final ConcatNonNullTypeComputer INSTANCE = new ConcatNonNullTypeComputer();
+
+    @Override
+    public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env,
+            IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
+        AbstractFunctionCallExpression f = (AbstractFunctionCallExpression) expression;
+        if (f.getArguments().size() < 1) {
+            return BuiltinType.ANULL;
+        }
+        List<IAType> possibleTypes = new ArrayList<IAType>();
+        for (int i = 0; i < f.getArguments().size(); i++) {
+            ILogicalExpression arg = f.getArguments().get(i).getValue();
+            IAType type = (IAType) env.getType(arg);
+            if (type.getTypeTag() == ATypeTag.UNION) {
+                List<IAType> typeList = ((AUnionType) type).getUnionList();
+                for (IAType t : typeList) {
+                    if (t.getTypeTag() != ATypeTag.NULL) {
+                        //CONCAT_NON_NULL cannot return null because it's only used for if-else construct
+                        if (!possibleTypes.contains(t))
+                            possibleTypes.add(t);
+                    }
+                }
+            } else {
+                if (!possibleTypes.contains(type))
+                    possibleTypes.add(type);
+            }
+        }
+        if (possibleTypes.size() == 1) {
+            return possibleTypes.get(0);
+        } else {
+            throw new AlgebricksException("The two branches of the if-else clause should return the same type.");
+        }
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/GetItemDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/GetItemDescriptor.java
index b41347d..c30fb6d 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/GetItemDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/GetItemDescriptor.java
@@ -109,7 +109,7 @@
                         }
                         if (itemIndex < 0)
                             throw new AlgebricksException(AsterixBuiltinFunctions.GET_ITEM.getName()
-                                    + ": item index can be negative!");
+                                    + ": item index cannot be negative!");
 
                         itemTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serOrderedList[1]);
                         if (itemTag == ATypeTag.ANY)