[ASTERIXDB-3585][FUN] NULLIF(V1, V2) return V1 when V1=V2 is false/null/missing

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

Details:
NULLIF(V1, V2) should return V1 when V1 = V2 evaluates to false, null, or missing.

- if_inf(): skip MISSING arg values.

Ext-ref: MB-37298

Change-Id: I7ab2f4f5edb5c3afbcc7d1aff972b03b25b5e4ad
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19557
Reviewed-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
Reviewed-by: Murtadha Hubail <mhubail@apache.org>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/runtime/NullMissingTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/runtime/NullMissingTest.java
index cf30c4d..3a52aa7 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/runtime/NullMissingTest.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/runtime/NullMissingTest.java
@@ -210,10 +210,5 @@
         functionsRequiringTypes.add(BuiltinFunctions.GE);
         functionsRequiringTypes.add(BuiltinFunctions.LE);
         functionsRequiringTypes.add(BuiltinFunctions.NEQ);
-        functionsRequiringTypes.add(BuiltinFunctions.MISSING_IF);
-        functionsRequiringTypes.add(BuiltinFunctions.NAN_IF);
-        functionsRequiringTypes.add(BuiltinFunctions.NEGINF_IF);
-        functionsRequiringTypes.add(BuiltinFunctions.NULL_IF);
-        functionsRequiringTypes.add(BuiltinFunctions.POSINF_IF);
     }
 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/missingif/missingif.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/missingif/missingif.1.adm
index b0a2b5a..1077714 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/missingif/missingif.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/missingif/missingif.1.adm
@@ -1 +1 @@
-{ "t1": true, "t2": true, "t3": true, "t4": true, "t5": true, "t6": true, "t7": true, "t8": true }
\ No newline at end of file
+{ "t1": true, "t2": true, "t3": false, "t4": true, "t5": false, "t6": true, "t7": true, "t8": false }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/nanif/nanif.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/nanif/nanif.1.adm
index b0a2b5a..1077714 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/nanif/nanif.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/nanif/nanif.1.adm
@@ -1 +1 @@
-{ "t1": true, "t2": true, "t3": true, "t4": true, "t5": true, "t6": true, "t7": true, "t8": true }
\ No newline at end of file
+{ "t1": true, "t2": true, "t3": false, "t4": true, "t5": false, "t6": true, "t7": true, "t8": false }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/neginfif/neginfif.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/neginfif/neginfif.1.adm
index b0a2b5a..1077714 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/neginfif/neginfif.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/neginfif/neginfif.1.adm
@@ -1 +1 @@
-{ "t1": true, "t2": true, "t3": true, "t4": true, "t5": true, "t6": true, "t7": true, "t8": true }
\ No newline at end of file
+{ "t1": true, "t2": true, "t3": false, "t4": true, "t5": false, "t6": true, "t7": true, "t8": false }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/nullif/nullif.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/nullif/nullif.1.adm
index b0a2b5a..1077714 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/nullif/nullif.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/nullif/nullif.1.adm
@@ -1 +1 @@
-{ "t1": true, "t2": true, "t3": true, "t4": true, "t5": true, "t6": true, "t7": true, "t8": true }
\ No newline at end of file
+{ "t1": true, "t2": true, "t3": false, "t4": true, "t5": false, "t6": true, "t7": true, "t8": false }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/posinfif/posinfif.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/posinfif/posinfif.1.adm
index b0a2b5a..1077714 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/posinfif/posinfif.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/posinfif/posinfif.1.adm
@@ -1 +1 @@
-{ "t1": true, "t2": true, "t3": true, "t4": true, "t5": true, "t6": true, "t7": true, "t8": true }
\ No newline at end of file
+{ "t1": true, "t2": true, "t3": false, "t4": true, "t5": false, "t6": true, "t7": true, "t8": false }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/ifinf/ifinf.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/ifinf/ifinf.1.adm
index 8b239c2..4593ec2 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/ifinf/ifinf.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/ifinf/ifinf.1.adm
@@ -1,5 +1,5 @@
 [ 1, true ]
-[ 2, true ]
+[ 2, false ]
 [ 3, true ]
 [ 4, true ]
 [ 5, true ]
@@ -12,11 +12,11 @@
 [ 12, 2.5 ]
 [ 13, 2 ]
 [ 14, true ]
-[ 15, true ]
+[ 15, false ]
 [ 16, 2 ]
 [ 17, 2 ]
 [ 18, true ]
-[ 19, true ]
+[ 19, false ]
 [ 20, "NaN" ]
 [ 21, 2 ]
 [ 22, null ]
\ No newline at end of file
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
index 27f2160..2bf5adc 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
@@ -1554,10 +1554,10 @@
         addPrivateFunction(TREAT_AS_INTEGER, TreatAsTypeComputer.INSTANCE_INTEGER, true);
         addPrivateFunction(IS_NUMERIC_ADD_COMPATIBLE, BooleanOnlyTypeComputer.INSTANCE, true);
 
-        addFunction(IF_INF, IfNanOrInfTypeComputer.INSTANCE, true);
         addFunction(IF_MISSING, IfMissingTypeComputer.INSTANCE, true);
         addFunction(IF_MISSING_OR_NULL, IfMissingOrNullTypeComputer.INSTANCE, true);
         addFunction(IF_NULL, IfNullTypeComputer.INSTANCE, true);
+        addFunction(IF_INF, IfNanOrInfTypeComputer.INSTANCE_SKIP_MISSING, true);
         addFunction(IF_NAN, IfNanOrInfTypeComputer.INSTANCE_SKIP_MISSING, true);
         addFunction(IF_NAN_OR_INF, IfNanOrInfTypeComputer.INSTANCE_SKIP_MISSING, true);
         addPrivateFunction(IF_SYSTEM_NULL, IfNullTypeComputer.INSTANCE, true);
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/DoubleIfTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/DoubleIfTypeComputer.java
index 105ea52..83c560f 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/DoubleIfTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/DoubleIfTypeComputer.java
@@ -19,20 +19,48 @@
 
 package org.apache.asterix.om.typecomputer.impl;
 
-import org.apache.asterix.om.typecomputer.base.AbstractResultTypeComputer;
+import java.util.List;
+
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
 import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AUnionType;
 import org.apache.asterix.om.types.BuiltinType;
 import org.apache.asterix.om.types.IAType;
+import org.apache.commons.lang3.mutable.Mutable;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
+import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
 
-public class DoubleIfTypeComputer extends AbstractResultTypeComputer {
+public class DoubleIfTypeComputer implements IResultTypeComputer {
 
     public static final DoubleIfTypeComputer INSTANCE = new DoubleIfTypeComputer();
 
     @Override
-    public IAType getResultType(ILogicalExpression expr, IAType... strippedInputTypes) throws AlgebricksException {
-        IAType inputType = strippedInputTypes[0];
-        return inputType.getTypeTag() == ATypeTag.DOUBLE ? inputType : BuiltinType.ANY;
+    public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env,
+            IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
+        AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) expression;
+        List<Mutable<ILogicalExpression>> arguments = fce.getArguments();
+        if (arguments.size() != 2) {
+            String functionName = fce.getFunctionIdentifier().getName();
+            throw new CompilationException(ErrorCode.COMPILATION_INVALID_NUM_OF_ARGS, fce.getSourceLocation(),
+                    functionName);
+        }
+        Mutable<ILogicalExpression> firstArg = arguments.get(0);
+        IAType firstArgType = (IAType) env.getType(firstArg.getValue());
+        if (firstArgType.getTypeTag() == ATypeTag.DOUBLE) {
+            return firstArgType;
+        } else if (firstArgType.getTypeTag() == ATypeTag.UNION) {
+            AUnionType unionType = (AUnionType) firstArgType;
+            IAType actualType = unionType.getActualType();
+            if (actualType.getTypeTag() == ATypeTag.DOUBLE && unionType.isUnknownableType()) {
+                return unionType;
+            }
+        }
+
+        return BuiltinType.ANY;
     }
 }
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/IfNanOrInfTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/IfNanOrInfTypeComputer.java
index a0423cd..061e691 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/IfNanOrInfTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/IfNanOrInfTypeComputer.java
@@ -31,13 +31,9 @@
 
 public class IfNanOrInfTypeComputer extends AbstractResultTypeComputer {
 
-    public static final IfNanOrInfTypeComputer INSTANCE = new IfNanOrInfTypeComputer(false);
-    public static final IfNanOrInfTypeComputer INSTANCE_SKIP_MISSING = new IfNanOrInfTypeComputer(true);
+    public static final IfNanOrInfTypeComputer INSTANCE_SKIP_MISSING = new IfNanOrInfTypeComputer();
 
-    private final boolean skipMissing;
-
-    private IfNanOrInfTypeComputer(boolean skipMissing) {
-        this.skipMissing = skipMissing;
+    private IfNanOrInfTypeComputer() {
     }
 
     @Override
@@ -63,10 +59,8 @@
 
         switch (currentType.getTypeTag()) {
             case MISSING:
-                if (skipMissing) {
-                    // i.e. all args have been inspected and couldn't find a candidate value, so return null
-                    return BuiltinType.ANULL;
-                }
+                // i.e. all args have been inspected and couldn't find a candidate value, so return null
+                return BuiltinType.ANULL;
             case ANY:
             case BIGINT:
             case INTEGER:
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/MissingIfTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/MissingIfTypeComputer.java
index bb5203e..3dc7e57 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/MissingIfTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/MissingIfTypeComputer.java
@@ -35,4 +35,9 @@
         IAType inputType = strippedInputTypes[0];
         return inputType.getTypeTag() == ATypeTag.ANY ? inputType : AUnionType.createMissableType(inputType);
     }
+
+    @Override
+    protected boolean propagateNullAndMissing() {
+        return false;
+    }
 }
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NullIfTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NullIfTypeComputer.java
index 590d8f6..27473e3 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NullIfTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NullIfTypeComputer.java
@@ -35,4 +35,9 @@
         IAType inputType = strippedInputTypes[0];
         return inputType.getTypeTag() == ATypeTag.ANY ? inputType : AUnionType.createNullableType(inputType);
     }
+
+    @Override
+    protected boolean propagateNullAndMissing() {
+        return false;
+    }
 }
diff --git a/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/TypeComputerTest.java b/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/TypeComputerTest.java
index cbcb8b3..820c956 100644
--- a/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/TypeComputerTest.java
+++ b/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/TypeComputerTest.java
@@ -34,6 +34,7 @@
 import org.apache.asterix.om.typecomputer.impl.BooleanOnlyTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.BooleanOrMissingTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.ClosedRecordConstructorResultType;
+import org.apache.asterix.om.typecomputer.impl.DoubleIfTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.InjectFailureTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.LocalAvgTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.LocalMedianTypeComputer;
@@ -162,10 +163,8 @@
             // Ensure the field is one of the instances of the class
             if (field.getType().equals(clazz)) {
                 LOGGER.log(Level.INFO, "Testing " + clazz.getSimpleName() + ": " + field.getName());
-
-                when(functionCallExpression.getArguments()).thenReturn(sixArgs);
-
                 instance = (IResultTypeComputer) field.get(null);
+                when(functionCallExpression.getArguments()).thenReturn(argsFor(instance, sixArgs));
                 resultType = instance.computeType(functionCallExpression, typeEnv, metadataProvider);
                 ATypeTag typeTag = resultType.getTypeTag();
 
@@ -176,6 +175,14 @@
         }
     }
 
+    private static List<Mutable<ILogicalExpression>> argsFor(IResultTypeComputer typeComputer,
+            List<Mutable<ILogicalExpression>> sixArgs) {
+        if (typeComputer.getClass() == DoubleIfTypeComputer.class) {
+            return sixArgs.subList(0, 2);
+        }
+        return sixArgs;
+    }
+
     public static void prepare() {
         // Add to exception list for computers having a different behavior for "any" type
         addComputersBehavingDifferently();
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractComparisonEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractComparisonEvaluator.java
index 4747475..6c6c760 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractComparisonEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractComparisonEvaluator.java
@@ -80,11 +80,13 @@
     private final ILogicalBinaryComparator logicalComparator;
     private final IAObject leftConstant;
     private final IAObject rightConstant;
+    private final boolean checkUnknown;
 
     AbstractComparisonEvaluator(IScalarEvaluatorFactory evalLeftFactory, IAType leftType,
             IScalarEvaluatorFactory evalRightFactory, IAType rightType, IEvaluatorContext ctx, SourceLocation sourceLoc,
-            boolean isEquality) throws HyracksDataException {
+            boolean isEquality, boolean checkUnknown) throws HyracksDataException {
         this.ctx = ctx;
+        this.checkUnknown = checkUnknown;
         this.evalLeft = evalLeftFactory.createScalarEvaluator(ctx);
         this.evalRight = evalRightFactory.createScalarEvaluator(ctx);
         this.sourceLoc = sourceLoc;
@@ -103,7 +105,7 @@
         evalLeft.evaluate(tuple, argLeft);
         evalRight.evaluate(tuple, argRight);
 
-        if (PointableHelper.checkAndSetMissingOrNull(result, argLeft, argRight)) {
+        if (checkUnknown && PointableHelper.checkAndSetMissingOrNull(result, argLeft, argRight)) {
             return;
         }
         leftVal.set(argLeft.getByteArray(), argLeft.getStartOffset() + 1, argLeft.getLength() - 1,
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractIfEqualsEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractIfEqualsEvaluator.java
index c3a7dbc..a23598f 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractIfEqualsEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractIfEqualsEvaluator.java
@@ -19,6 +19,7 @@
 
 package org.apache.asterix.runtime.evaluators.comparisons;
 
+import org.apache.asterix.dataflow.data.common.ILogicalBinaryComparator;
 import org.apache.asterix.om.types.IAType;
 import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
 import org.apache.hyracks.api.context.IEvaluatorContext;
@@ -31,26 +32,17 @@
     AbstractIfEqualsEvaluator(IScalarEvaluatorFactory evalLeftFactory, IAType leftType,
             IScalarEvaluatorFactory evalRightFactory, IAType rightType, IEvaluatorContext ctx, SourceLocation sourceLoc)
             throws HyracksDataException {
-        super(evalLeftFactory, leftType, evalRightFactory, rightType, ctx, sourceLoc, true);
+        super(evalLeftFactory, leftType, evalRightFactory, rightType, ctx, sourceLoc, true, false);
     }
 
     @Override
     protected void evaluateImpl(IPointable result) throws HyracksDataException {
-        // TODO(ali): revisit this for the cases of MISSING/NULL/INCOMPARABLE
-        switch (compare()) {
-            case MISSING:
-                writeMissing(result);
-                break;
-            case NULL:
-                writeNull(result);
-                break;
-            case EQ:
-                resultStorage.reset();
-                writeEqualsResult();
-                result.set(resultStorage);
-                break;
-            default:
-                result.set(argLeft);
+        if (compare() == ILogicalBinaryComparator.Result.EQ) {
+            resultStorage.reset();
+            writeEqualsResult();
+            result.set(resultStorage);
+        } else {
+            result.set(argLeft);
         }
     }
 
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractValueComparisonEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractValueComparisonEvaluator.java
index 27f117f..bb6a3fe 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractValueComparisonEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractValueComparisonEvaluator.java
@@ -42,7 +42,7 @@
     public AbstractValueComparisonEvaluator(IScalarEvaluatorFactory evalLeftFactory, IAType leftType,
             IScalarEvaluatorFactory evalRightFactory, IAType rightType, IEvaluatorContext ctx, SourceLocation sourceLoc,
             boolean isEquality) throws HyracksDataException {
-        super(evalLeftFactory, leftType, evalRightFactory, rightType, ctx, sourceLoc, isEquality);
+        super(evalLeftFactory, leftType, evalRightFactory, rightType, ctx, sourceLoc, isEquality, true);
     }
 
     @Override
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/MissingIfEqualsDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/MissingIfEqualsDescriptor.java
index 529cd0d..6554c74 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/MissingIfEqualsDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/MissingIfEqualsDescriptor.java
@@ -19,7 +19,6 @@
 
 package org.apache.asterix.runtime.evaluators.comparisons;
 
-import org.apache.asterix.common.annotations.MissingNullInOutFunction;
 import org.apache.asterix.om.base.AMissing;
 import org.apache.asterix.om.functions.BuiltinFunctions;
 import org.apache.asterix.om.functions.IFunctionDescriptor;
@@ -32,7 +31,6 @@
 import org.apache.hyracks.api.context.IEvaluatorContext;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 
-@MissingNullInOutFunction
 public class MissingIfEqualsDescriptor extends AbstractComparisonDescriptor {
     private static final long serialVersionUID = 1L;
 
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/NanIfEqualsDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/NanIfEqualsDescriptor.java
index 26e76cd..632e602 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/NanIfEqualsDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/NanIfEqualsDescriptor.java
@@ -19,7 +19,6 @@
 
 package org.apache.asterix.runtime.evaluators.comparisons;
 
-import org.apache.asterix.common.annotations.MissingNullInOutFunction;
 import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
 import org.apache.asterix.om.base.ADouble;
 import org.apache.asterix.om.base.AMutableDouble;
@@ -36,7 +35,6 @@
 import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 
-@MissingNullInOutFunction
 public class NanIfEqualsDescriptor extends AbstractComparisonDescriptor {
     private static final long serialVersionUID = 1L;
 
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/NegInfIfEqualsDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/NegInfIfEqualsDescriptor.java
index e403a1e..3c9571a 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/NegInfIfEqualsDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/NegInfIfEqualsDescriptor.java
@@ -19,7 +19,6 @@
 
 package org.apache.asterix.runtime.evaluators.comparisons;
 
-import org.apache.asterix.common.annotations.MissingNullInOutFunction;
 import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
 import org.apache.asterix.om.base.ADouble;
 import org.apache.asterix.om.base.AMutableDouble;
@@ -36,7 +35,6 @@
 import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 
-@MissingNullInOutFunction
 public class NegInfIfEqualsDescriptor extends AbstractComparisonDescriptor {
     private static final long serialVersionUID = 1L;
 
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/NullIfEqualsDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/NullIfEqualsDescriptor.java
index 1b1d08f..0d6083f 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/NullIfEqualsDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/NullIfEqualsDescriptor.java
@@ -19,7 +19,6 @@
 
 package org.apache.asterix.runtime.evaluators.comparisons;
 
-import org.apache.asterix.common.annotations.MissingNullInOutFunction;
 import org.apache.asterix.om.base.ANull;
 import org.apache.asterix.om.functions.BuiltinFunctions;
 import org.apache.asterix.om.functions.IFunctionDescriptor;
@@ -32,7 +31,6 @@
 import org.apache.hyracks.api.context.IEvaluatorContext;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 
-@MissingNullInOutFunction
 public class NullIfEqualsDescriptor extends AbstractComparisonDescriptor {
     private static final long serialVersionUID = 1L;
 
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/PosInfIfEqualsDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/PosInfIfEqualsDescriptor.java
index 5273d52..3876d24 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/PosInfIfEqualsDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/PosInfIfEqualsDescriptor.java
@@ -19,7 +19,6 @@
 
 package org.apache.asterix.runtime.evaluators.comparisons;
 
-import org.apache.asterix.common.annotations.MissingNullInOutFunction;
 import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
 import org.apache.asterix.om.base.ADouble;
 import org.apache.asterix.om.base.AMutableDouble;
@@ -36,7 +35,6 @@
 import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 
-@MissingNullInOutFunction
 public class PosInfIfEqualsDescriptor extends AbstractComparisonDescriptor {
     private static final long serialVersionUID = 1L;
 
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfInfDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfInfDescriptor.java
index 1a6c7c1..0cceaa3 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfInfDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfInfDescriptor.java
@@ -30,9 +30,8 @@
 
 /**
  * ifinf(arg1, arg2, ...) scans the list of arguments in order and returns the first numeric argument it encounters.
- * If the argument being inspected is infinity as determined by the mathematical definition of floating-points, then
- * it skips the argument and inspects the next one. It returns missing if the argument being inspected is missing.
- * It returns null if:
+ * If the argument being inspected is missing or infinity as determined by the mathematical definition of
+ * floating-points, then it skips the argument and inspects the next one. It returns null if:
  * 1. the argument being inspected is not numeric.
  * 2. all the arguments have been inspected and no candidate value has been found.
  *
@@ -50,7 +49,7 @@
 
             @Override
             public IScalarEvaluator createScalarEvaluator(final IEvaluatorContext ctx) throws HyracksDataException {
-                return new IfNanOrInfDescriptor.AbstractIfInfOrNanEval(ctx, args, false) {
+                return new IfNanOrInfDescriptor.AbstractIfInfOrNanEval(ctx, args) {
                     @Override
                     protected boolean skipDouble(double d) {
                         return Double.isInfinite(d);
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNanDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNanDescriptor.java
index 6872c6a..c35cabb 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNanDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNanDescriptor.java
@@ -49,7 +49,7 @@
 
             @Override
             public IScalarEvaluator createScalarEvaluator(final IEvaluatorContext ctx) throws HyracksDataException {
-                return new IfNanOrInfDescriptor.AbstractIfInfOrNanEval(ctx, args, true) {
+                return new IfNanOrInfDescriptor.AbstractIfInfOrNanEval(ctx, args) {
                     @Override
                     protected boolean skipDouble(double d) {
                         return Double.isNaN(d);
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNanOrInfDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNanOrInfDescriptor.java
index 17c4e46..3218822 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNanOrInfDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNanOrInfDescriptor.java
@@ -58,7 +58,7 @@
 
             @Override
             public IScalarEvaluator createScalarEvaluator(final IEvaluatorContext ctx) throws HyracksDataException {
-                return new AbstractIfInfOrNanEval(ctx, args, true) {
+                return new AbstractIfInfOrNanEval(ctx, args) {
                     @Override
                     protected boolean skipDouble(double d) {
                         return Double.isInfinite(d) || Double.isNaN(d);
@@ -88,16 +88,13 @@
         private final IScalarEvaluator[] argEvals;
 
         private final IPointable argPtr;
-        private final boolean skipMissing;
 
-        AbstractIfInfOrNanEval(IEvaluatorContext ctx, IScalarEvaluatorFactory[] args, boolean skipMissing)
-                throws HyracksDataException {
+        AbstractIfInfOrNanEval(IEvaluatorContext ctx, IScalarEvaluatorFactory[] args) throws HyracksDataException {
             argEvals = new IScalarEvaluator[args.length];
             for (int i = 0; i < argEvals.length; i++) {
                 argEvals[i] = args[i].createScalarEvaluator(ctx);
             }
             argPtr = new VoidPointable();
-            this.skipMissing = skipMissing;
         }
 
         @Override
@@ -124,9 +121,7 @@
                         result.set(argPtr);
                         return;
                     case MISSING:
-                        if (skipMissing) {
-                            continue;
-                        }
+                        continue;
                     case BIGINT:
                     case INTEGER:
                     case SMALLINT: