[ASTERIXDB-2928][IDX] Array index support for SOME AND EVERY.

- user mode changes: no
- storage format changes: no
- interface changes: no

Adding support to use SOME AND EVERY for universal quantification
applicability recognition with array indexes, and updating the docs to
use this in leiu of the old LEN(array field) > 0 clause to indicate that
the array is non-empty.

Change-Id: I0129f5b4d1058a7d2a4d3f0eadfe59e55d693461
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/12603
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Dmitry Lychagin <dmitry.lychagin@couchbase.com>
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/AbstractOperatorFromSubplanCreator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/AbstractOperatorFromSubplanCreator.java
index 9fd14cc..8fa7981 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/AbstractOperatorFromSubplanCreator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/AbstractOperatorFromSubplanCreator.java
@@ -41,6 +41,7 @@
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
+import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.AggregateFunctionCallExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.IAlgebricksConstantValue;
@@ -53,6 +54,7 @@
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.SubplanOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities;
 import org.apache.hyracks.algebricks.core.algebra.util.OperatorManipulationUtil;
 import org.apache.hyracks.api.exceptions.SourceLocation;
 
@@ -78,6 +80,22 @@
         this.context = context;
     }
 
+    protected LogicalVariable getConditioningVariable(ILogicalExpression condition) {
+        List<Mutable<ILogicalExpression>> selectConjuncts = new ArrayList<>();
+        if (condition.splitIntoConjuncts(selectConjuncts)) {
+            for (Mutable<ILogicalExpression> conjunct : selectConjuncts) {
+                if (conjunct.getValue().getExpressionTag().equals(LogicalExpressionTag.VARIABLE)) {
+                    return ((VariableReferenceExpression) conjunct.getValue()).getVariableReference();
+                }
+            }
+
+        } else if (condition.getExpressionTag().equals(LogicalExpressionTag.VARIABLE)) {
+            return ((VariableReferenceExpression) condition).getVariableReference();
+
+        }
+        return null;
+    }
+
     protected Pair<SelectOperator, UnnestOperator> traverseSubplanBranch(SubplanOperator subplanOperator,
             ILogicalOperator parentInput) throws AlgebricksException {
         // We only expect one plan, and one root.
@@ -94,43 +112,26 @@
         }
         workingSubplanRootAsAggregate = (AggregateOperator) workingSubplanRoot;
 
-        // Try to find a SELECT that we can optimize (i.e. has a function call).
-        Pair<SelectOperator, UnnestOperator> traversalOutput;
-        SelectOperator optimizableSelect = null;
-        for (Mutable<ILogicalOperator> opInput : workingSubplanRoot.getInputs()) {
-            ILogicalOperator subplanOrSelect = findSubplanOrOptimizableSelect(opInput.getValue(), optimizableFunctions);
-            if (subplanOrSelect == null) {
-                return null;
-
-            } else if (subplanOrSelect.getOperatorTag().equals(LogicalOperatorTag.SUBPLAN)) {
-                traversalOutput = traverseSubplanBranch((SubplanOperator) subplanOrSelect, opInput.getValue());
-                if (traversalOutput != null) {
-                    optimizableSelect = traversalOutput.first;
-                }
-
-            } else {
-                optimizableSelect = (SelectOperator) subplanOrSelect;
-                break;
-            }
-        }
+        // Find (or create, in the SOME AND EVERY case) a SELECT that we can potentially optimize.
+        SelectOperator optimizableSelect = getSelectFromPlan(workingSubplanRootAsAggregate);
         if (optimizableSelect == null) {
             return null;
         }
 
         // We have found a SELECT with a variable. Create a copy, and set this to our rewrite root.
-        SelectOperator newSelectOperator = new SelectOperator(optimizableSelect.getCondition(),
+        SelectOperator rewriteRootSelect = new SelectOperator(optimizableSelect.getCondition(),
                 optimizableSelect.getRetainMissing(), optimizableSelect.getMissingPlaceholderVariable());
 
         // Ensure that this SELECT represents a predicate for an existential query, and is a query we can optimize.
-        newSelectOperator = normalizeSelectCondition(workingSubplanRootAsAggregate, newSelectOperator);
-        if (newSelectOperator == null) {
+        rewriteRootSelect = normalizeSelectCondition(workingSubplanRootAsAggregate, rewriteRootSelect);
+        if (rewriteRootSelect == null) {
             return null;
         }
-        newSelectOperator.setSourceLocation(sourceLocation);
-        newSelectOperator.setExecutionMode(optimizableSelect.getExecutionMode());
+        rewriteRootSelect.setSourceLocation(sourceLocation);
+        rewriteRootSelect.setExecutionMode(optimizableSelect.getExecutionMode());
 
         // Follow this SELECT to the root of our nested-plan branch (i.e. the NESTED-TUPLE-SOURCE).
-        ILogicalOperator workingNewOperator = newSelectOperator;
+        ILogicalOperator workingNewOperator = rewriteRootSelect;
         UnnestOperator bottommostNewUnnest = null;
         ILogicalOperator workingOriginalOperator = optimizableSelect.getInputs().get(0).getValue();
         while (!workingOriginalOperator.getOperatorTag().equals(LogicalOperatorTag.NESTEDTUPLESOURCE)) {
@@ -164,8 +165,8 @@
                     // If we encounter another SELECT, then we have multiple quantifiers. Transform our new SELECT to
                     // include this condition.
                     List<Mutable<ILogicalExpression>> selectArguments = new ArrayList<>();
-                    if (!newSelectOperator.getCondition().getValue().splitIntoConjuncts(selectArguments)) {
-                        selectArguments.add(newSelectOperator.getCondition());
+                    if (!rewriteRootSelect.getCondition().getValue().splitIntoConjuncts(selectArguments)) {
+                        selectArguments.add(rewriteRootSelect.getCondition());
                     }
                     if (!((SelectOperator) workingOriginalOperator).getCondition().getValue()
                             .splitIntoConjuncts(selectArguments)) {
@@ -174,10 +175,10 @@
                     ScalarFunctionCallExpression andCond = new ScalarFunctionCallExpression(
                             BuiltinFunctions.getBuiltinFunctionInfo(BuiltinFunctions.AND), selectArguments);
                     SelectOperator updatedSelectOperator = new SelectOperator(new MutableObject<>(andCond),
-                            newSelectOperator.getRetainMissing(), newSelectOperator.getMissingPlaceholderVariable());
+                            rewriteRootSelect.getRetainMissing(), rewriteRootSelect.getMissingPlaceholderVariable());
                     updatedSelectOperator.setSourceLocation(sourceLocation);
-                    updatedSelectOperator.getInputs().addAll(newSelectOperator.getInputs());
-                    newSelectOperator = updatedSelectOperator;
+                    updatedSelectOperator.getInputs().addAll(rewriteRootSelect.getInputs());
+                    rewriteRootSelect = updatedSelectOperator;
                     break;
 
                 case AGGREGATE:
@@ -196,9 +197,9 @@
                     "UNNEST expected in nested plan branch, but not found.");
         }
 
-        // If we are working with universal quantification, then we must also check whether or not we have a conjunct 
-        // that asserts that the array should also be non-empty.
-        if (isUniversalQuantification(workingSubplanRootAsAggregate)
+        // If we are working with strict universal quantification, then we must also check whether or not we have a
+        // conjunct that asserts that the array should also be non-empty.
+        if (isStrictUniversalQuantification(workingSubplanRootAsAggregate)
                 && isArrayNonEmptyConjunctMissing(bottommostNewUnnest, subplanOperator.getInputs().get(0).getValue())
                 && (parentInput == null || isArrayNonEmptyConjunctMissing(bottommostNewUnnest, parentInput))) {
             return null;
@@ -207,26 +208,84 @@
         // We have added everything we need in our nested-plan branch. Now, connect the input of our SUBPLAN to our
         // current working branch.
         bottommostNewUnnest.getInputs().addAll(subplanOperator.getInputs());
-        OperatorManipulationUtil.computeTypeEnvironmentBottomUp(newSelectOperator, context);
+        OperatorManipulationUtil.computeTypeEnvironmentBottomUp(rewriteRootSelect, context);
 
-        return new Pair<>(newSelectOperator, bottommostNewUnnest);
+        return new Pair<>(rewriteRootSelect, bottommostNewUnnest);
     }
 
-    private boolean isUniversalQuantification(AggregateOperator workingSubplanRoot) throws CompilationException {
-        AggregateFunctionCallExpression aggregateFunctionCallExpression =
-                (AggregateFunctionCallExpression) workingSubplanRoot.getExpressions().get(0).getValue();
-        if (aggregateFunctionCallExpression.getFunctionIdentifier().equals(BuiltinFunctions.EMPTY_STREAM)) {
-            return true;
+    protected SelectOperator getSelectFromPlan(AggregateOperator subplanRoot) throws AlgebricksException {
+        ILogicalOperator subplanRootInput = subplanRoot.getInputs().get(0).getValue();
+        ILogicalOperator subplanOrSelect = findSubplanOrOptimizableSelect(subplanRootInput);
 
-        } else if (aggregateFunctionCallExpression.getFunctionIdentifier().equals(BuiltinFunctions.NON_EMPTY_STREAM)) {
-            return false;
+        if (subplanOrSelect != null && subplanOrSelect.getOperatorTag().equals(LogicalOperatorTag.SUBPLAN)) {
+            // We have found a SUBPLAN. Recurse by calling our caller.
+            Pair<SelectOperator, UnnestOperator> traversalOutput =
+                    traverseSubplanBranch((SubplanOperator) subplanOrSelect, subplanRootInput);
+            return (traversalOutput != null) ? traversalOutput.first : null;
+
+        } else if (subplanOrSelect != null && subplanOrSelect.getOperatorTag().equals(LogicalOperatorTag.SELECT)) {
+            // We have found a SELECT. Return this to our caller.
+            return (SelectOperator) subplanOrSelect;
 
         } else {
-            throw new CompilationException(ErrorCode.COMPILATION_ERROR, workingSubplanRoot.getSourceLocation(),
-                    "Unexpected aggregate function: " + aggregateFunctionCallExpression.getFunctionIdentifier());
+            // We were not able to find a SELECT or a SUBPLAN. Try to find an expression in our aggregate that we
+            // can optimize (i.e. handle SOME AND EVERY case).
+            AbstractFunctionCallExpression optimizableCondition = null;
+            boolean isNonEmptyStream = false;
+            for (Mutable<ILogicalExpression> expression : subplanRoot.getExpressions()) {
+                AggregateFunctionCallExpression aggExpression = (AggregateFunctionCallExpression) expression.getValue();
+                if (aggExpression.getFunctionIdentifier().equals(BuiltinFunctions.NON_EMPTY_STREAM)) {
+                    isNonEmptyStream = true;
+
+                } else if (aggExpression.isTwoStep()
+                        && aggExpression.getStepOneAggregate().getFunctionIdentifier()
+                                .equals(BuiltinFunctions.SQL_COUNT)
+                        && aggExpression.getStepTwoAggregate().getFunctionIdentifier().equals(BuiltinFunctions.SQL_SUM)
+                        && aggExpression.getArguments().get(0).getValue().getExpressionTag()
+                                .equals(LogicalExpressionTag.FUNCTION_CALL)) {
+                    AbstractFunctionCallExpression switchExpression =
+                            (AbstractFunctionCallExpression) aggExpression.getArguments().get(0).getValue();
+                    if (!switchExpression.getArguments().get(0).getValue().getExpressionTag()
+                            .equals(LogicalExpressionTag.FUNCTION_CALL)) {
+                        continue;
+                    }
+                    AbstractFunctionCallExpression switchCondition =
+                            (AbstractFunctionCallExpression) switchExpression.getArguments().get(0).getValue();
+
+                    ILogicalExpression arg2 = switchExpression.getArguments().get(1).getValue();
+                    ILogicalExpression arg3 = switchExpression.getArguments().get(2).getValue();
+                    ILogicalExpression arg4 = switchExpression.getArguments().get(3).getValue();
+                    if (arg2.getExpressionTag().equals(LogicalExpressionTag.CONSTANT)
+                            && arg3.getExpressionTag().equals(LogicalExpressionTag.CONSTANT)
+                            && arg4.getExpressionTag().equals(LogicalExpressionTag.CONSTANT)
+                            && ((ConstantExpression) arg2).getValue().isTrue()
+                            && ((ConstantExpression) arg3).getValue().isNull()
+                            && ((ConstantExpression) arg4).getValue().isTrue()) {
+                        optimizableCondition = switchCondition;
+                    }
+                }
+            }
+            if (isNonEmptyStream && optimizableCondition != null) {
+                SelectOperator newSelectFromAggregate =
+                        new SelectOperator(new MutableObject<>(optimizableCondition), false, null);
+                newSelectFromAggregate.getInputs().addAll(subplanRoot.getInputs());
+                newSelectFromAggregate.setSourceLocation(sourceLocation);
+                return newSelectFromAggregate;
+            }
+            return null;
         }
     }
 
+    private boolean isStrictUniversalQuantification(AggregateOperator workingSubplanRoot) {
+        for (Mutable<ILogicalExpression> expression : workingSubplanRoot.getExpressions()) {
+            AggregateFunctionCallExpression funcExpr = (AggregateFunctionCallExpression) expression.getValue();
+            if (funcExpr.getFunctionIdentifier().equals(BuiltinFunctions.EMPTY_STREAM)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private boolean isArrayNonEmptyConjunctMissing(UnnestOperator firstUnnestInNTS, ILogicalOperator subplanInput)
             throws AlgebricksException {
         UnnestingFunctionCallExpression unnestFunction =
@@ -299,22 +358,21 @@
             }
         }
 
-        // TODO (GLENN): Handle the cases 1) where the arrayVar is explicitly indexed, 2) the NOT function.
         return false;
     }
 
     private SelectOperator normalizeSelectCondition(AggregateOperator aggregateOperator, SelectOperator selectOperator)
             throws AlgebricksException {
-        // The purpose of this function is to remove the NOT(IF-MISSING-OR-NULL(...)) functions for a universal
+        // The purpose of this function is to remove the NOT(IF-MISSING-OR-NULL(...)) functions for a strict universal
         // quantification query. The {@code ArrayBTreeAccessMethod} does not recognize the former as optimizable
         // functions, so we remove them here. This SELECT will never make it to the final query plan (after the
         // {@code IntroduceSelectAccessMethodRule}), which allows us to get away with this logically incorrect branch.
-        if (aggregateOperator != null && !isUniversalQuantification(aggregateOperator)) {
-            // We are working with an existential quantification query. Do not modify the SELECT.
+        if (aggregateOperator != null && !isStrictUniversalQuantification(aggregateOperator)) {
+            // We are working with an existential quantification OR an EACH AND EVERY query. Do not modify the SELECT.
             return selectOperator;
 
         } else {
-            // We are working with a universal quantification query.
+            // We are working with a strict universal quantification query.
             ScalarFunctionCallExpression notFunction =
                     (ScalarFunctionCallExpression) selectOperator.getCondition().getValue();
             if (!notFunction.getFunctionIdentifier().equals(BuiltinFunctions.NOT)) {
@@ -335,13 +393,13 @@
         }
     }
 
-    private ILogicalOperator findSubplanOrOptimizableSelect(ILogicalOperator operator,
-            Set<FunctionIdentifier> optimizableFunctions) {
+    private ILogicalOperator findSubplanOrOptimizableSelect(ILogicalOperator operator) throws AlgebricksException {
         // We are trying to find a SELECT operator with an optimizable function call.
         if (operator.getOperatorTag().equals(LogicalOperatorTag.SELECT)) {
             SelectOperator selectOperator = (SelectOperator) operator;
             ILogicalExpression selectCondExpr = selectOperator.getCondition().getValue();
-            if (selectCondExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
+            boolean containsValidVar = isAnyVarFromUnnestOrAssign(operator);
+            if (containsValidVar && selectCondExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
 
                 // We have a NOT function call. Determine if this follows the NOT(IF-MISSING-OR-NULL(...)) pattern.
                 ScalarFunctionCallExpression notExpr = (ScalarFunctionCallExpression) selectCondExpr;
@@ -358,11 +416,11 @@
                     // Inside the NOT(IF-MISSING-OR-NULL(...)) is an optimizable function. Return this.
                     ScalarFunctionCallExpression ifMissingOrNullExpr = (ScalarFunctionCallExpression) notCondExpr;
                     ILogicalExpression finalExpr = ifMissingOrNullExpr.getArguments().get(0).getValue();
-                    if (doesExpressionContainOptimizableFunction(finalExpr, optimizableFunctions)) {
+                    if (doesExpressionContainOptimizableFunction(finalExpr)) {
                         return selectOperator;
                     }
 
-                } else if (doesExpressionContainOptimizableFunction(selectCondExpr, optimizableFunctions)) {
+                } else if (doesExpressionContainOptimizableFunction(selectCondExpr)) {
                     // We have an optimizable function. Return this.
                     return selectOperator;
 
@@ -374,23 +432,18 @@
         }
 
         // No matching operator found. Recurse on current operator input.
-        if (operator.getInputs().isEmpty()) {
-            return null;
-
-        } else {
-            return findSubplanOrOptimizableSelect(operator.getInputs().get(0).getValue(), optimizableFunctions);
-        }
+        return (operator.getInputs().isEmpty()) ? null
+                : findSubplanOrOptimizableSelect(operator.getInputs().get(0).getValue());
     }
 
-    private boolean doesExpressionContainOptimizableFunction(ILogicalExpression inputExpr,
-            Set<FunctionIdentifier> optimizableFunctions) {
+    private boolean doesExpressionContainOptimizableFunction(ILogicalExpression inputExpr) {
         if (!inputExpr.getExpressionTag().equals(LogicalExpressionTag.FUNCTION_CALL)) {
             return false;
         }
 
         // Check if the input expression itself is an optimizable function.
         ScalarFunctionCallExpression inputExprAsFunc = (ScalarFunctionCallExpression) inputExpr;
-        if (isFunctionOptimizable(inputExprAsFunc, optimizableFunctions)) {
+        if (isFunctionOptimizable(inputExprAsFunc)) {
             return true;
         }
 
@@ -400,8 +453,7 @@
             for (Mutable<ILogicalExpression> mutableConjunct : conjuncts) {
                 ILogicalExpression workingConjunct = mutableConjunct.getValue();
                 if (workingConjunct.getExpressionTag().equals(LogicalExpressionTag.FUNCTION_CALL)
-                        && (isFunctionOptimizable((ScalarFunctionCallExpression) workingConjunct,
-                                optimizableFunctions))) {
+                        && isFunctionOptimizable((ScalarFunctionCallExpression) workingConjunct)) {
                     return true;
                 }
             }
@@ -410,8 +462,7 @@
         return false;
     }
 
-    private boolean isFunctionOptimizable(ScalarFunctionCallExpression inputExpr,
-            Set<FunctionIdentifier> optimizableFunctions) {
+    private boolean isFunctionOptimizable(ScalarFunctionCallExpression inputExpr) {
         if (inputExpr.getFunctionIdentifier().equals(BuiltinFunctions.GT)) {
             // Avoid the GT(LEN(array-field), 0) function.
             ILogicalExpression gtExpr = inputExpr.getArguments().get(0).getValue();
@@ -431,4 +482,23 @@
         // Otherwise, check if the function itself is optimizable.
         return (optimizableFunctions.contains(inputExpr.getFunctionIdentifier()));
     }
+
+    private boolean isAnyVarFromUnnestOrAssign(ILogicalOperator op) throws AlgebricksException {
+        List<LogicalVariable> opUsedVars = new ArrayList<>(), relevantVars = new ArrayList<>();
+        VariableUtilities.getUsedVariables(op, opUsedVars);
+        ILogicalOperator workingOp = op;
+        boolean isMatchFound = false;
+        while (workingOp != null) {
+            if (workingOp.getOperatorTag().equals(LogicalOperatorTag.UNNEST)
+                    || workingOp.getOperatorTag().equals(LogicalOperatorTag.ASSIGN)) {
+                VariableUtilities.getProducedVariables(workingOp, relevantVars);
+                if (opUsedVars.stream().anyMatch(relevantVars::contains)) {
+                    isMatchFound = true;
+                    break;
+                }
+            }
+            workingOp = (workingOp.getInputs().isEmpty()) ? null : workingOp.getInputs().get(0).getValue();
+        }
+        return isMatchFound;
+    }
 }
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/JoinFromSubplanCreator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/JoinFromSubplanCreator.java
index 0e32703..9a11b98 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/JoinFromSubplanCreator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/JoinFromSubplanCreator.java
@@ -31,10 +31,7 @@
 import org.apache.hyracks.algebricks.common.utils.Pair;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
 import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
-import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
 import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.InnerJoinOperator;
@@ -42,7 +39,6 @@
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.SubplanOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities;
 import org.apache.hyracks.algebricks.core.algebra.util.OperatorManipulationUtil;
 
 /**
@@ -133,8 +129,7 @@
 
         // Additionally, verify that our SELECT is conditioning on a variable.
         joinContext.selectAfterSubplan = (SelectOperator) afterJoinOp2;
-        if (!joinContext.selectAfterSubplan.getCondition().getValue().getExpressionTag()
-                .equals(LogicalExpressionTag.VARIABLE)) {
+        if (getConditioningVariable(joinContext.selectAfterSubplan.getCondition().getValue()) == null) {
             return;
         }
 
@@ -175,18 +170,9 @@
             return null;
         }
 
-        // Verify that the subplan does not produce any other variable other than the SELECT var from its parent.
-        SelectOperator selectAfterSubplan = joinContext.selectAfterSubplan;
-        LogicalVariable originalSelectVar =
-                ((VariableReferenceExpression) selectAfterSubplan.getCondition().getValue()).getVariableReference();
-        SubplanOperator subplanOperator = (SubplanOperator) selectAfterSubplan.getInputs().get(0).getValue();
-        List<LogicalVariable> subplanProducedVars = new ArrayList<>();
-        VariableUtilities.getProducedVariables(subplanOperator, subplanProducedVars);
-        if (subplanProducedVars.size() != 1 || !subplanProducedVars.get(0).equals(originalSelectVar)) {
-            return null;
-        }
-
         // Traverse our subplan and generate a SELECT branch if applicable.
+        SubplanOperator subplanOperator =
+                (SubplanOperator) joinContext.selectAfterSubplan.getInputs().get(0).getValue();
         Pair<SelectOperator, UnnestOperator> traversalOutput =
                 traverseSubplanBranch(subplanOperator, originalOperator.getInputs().get(1).getValue());
         if (traversalOutput == null) {
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/SelectFromSubplanCreator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/SelectFromSubplanCreator.java
index 63b5692..6211ea3 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/SelectFromSubplanCreator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/SelectFromSubplanCreator.java
@@ -19,7 +19,6 @@
 package org.apache.asterix.optimizer.rules.subplan;
 
 import java.util.ArrayDeque;
-import java.util.ArrayList;
 import java.util.Deque;
 import java.util.HashSet;
 import java.util.List;
@@ -30,15 +29,12 @@
 import org.apache.hyracks.algebricks.common.utils.Pair;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
 import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
-import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
 import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.SubplanOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities;
 
 /**
  * For use in writing a "throwaway" branch which removes NTS and subplan operators. The result of this invocation is to
@@ -113,23 +109,14 @@
         reset(originalOperator.getSourceLocation(), context, optimizableFunctions);
 
         // We expect a) a SUBPLAN as input to this SELECT, and b) our SELECT to be conditioning on a variable.
+        LogicalVariable originalSelectVar = getConditioningVariable(originalOperator.getCondition().getValue());
         if (!originalOperator.getInputs().get(0).getValue().getOperatorTag().equals(LogicalOperatorTag.SUBPLAN)
-                || !originalOperator.getCondition().getValue().getExpressionTag()
-                        .equals(LogicalExpressionTag.VARIABLE)) {
-            return null;
-        }
-        LogicalVariable originalSelectVar =
-                ((VariableReferenceExpression) originalOperator.getCondition().getValue()).getVariableReference();
-
-        // Additionally, verify that the subplan does not produce any other variable other than the SELECT var above.
-        SubplanOperator subplanOperator = (SubplanOperator) originalOperator.getInputs().get(0).getValue();
-        List<LogicalVariable> subplanProducedVars = new ArrayList<>();
-        VariableUtilities.getProducedVariables(subplanOperator, subplanProducedVars);
-        if (subplanProducedVars.size() != 1 || !subplanProducedVars.get(0).equals(originalSelectVar)) {
+                || originalSelectVar == null) {
             return null;
         }
 
         // Traverse our subplan and generate a SELECT branch if applicable.
+        SubplanOperator subplanOperator = (SubplanOperator) originalOperator.getInputs().get(0).getValue();
         Pair<SelectOperator, UnnestOperator> traversalOutput = traverseSubplanBranch(subplanOperator, null);
         return (traversalOutput == null) ? null : traversalOutput.first;
     }
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-1/query5.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-1/query5.sqlpp
new file mode 100644
index 0000000..3da4d0c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-1/query5.sqlpp
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+SET `compiler.arrayindex` "true";
+
+DROP DATAVERSE TestYelp IF EXISTS;
+CREATE DATAVERSE TestYelp;
+USE TestYelp;
+
+CREATE TYPE CheckinType AS {
+    checkin_id: uuid,
+    business_id: string,
+    dates: [string]
+    };
+CREATE TYPE CheckinDatesToMarkersType AS {
+    marker: string,
+    datetime: string,
+    date: string,
+    time: string
+    };
+
+CREATE DATASET YelpCheckin(CheckinType) PRIMARY KEY checkin_id AUTOGENERATED;
+CREATE DATASET YelpCheckinDateMarkers (CheckinDatesToMarkersType) PRIMARY KEY marker;
+CREATE INDEX IdxYelpCheckinDates ON YelpCheckin (UNNEST dates);
+
+FROM    YelpCheckinDateMarkers M, YelpCheckin C
+WHERE   C.business_id = "--Ni3oJ4VOqfOEu7Sj2Vzg" AND
+        ( SOME AND EVERY D IN C.dates
+          SATISFIES M.date /*+ indexnl */ = D )
+SELECT  COUNT(*);
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-2/query2.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-2/query2.sqlpp
index d612e71..9e317ac 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-2/query2.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-2/query2.sqlpp
@@ -43,7 +43,6 @@
 
 FROM    YelpCheckinDateMarkers M, YelpCheckin C
 WHERE   C.business_id = "--Ni3oJ4VOqfOEu7Sj2Vzg" AND
-        LEN(C.checkin_times.dates) > 0 AND
-        ( EVERY D IN C.checkin_times.dates
+        ( SOME AND EVERY D IN C.checkin_times.dates
           SATISFIES M.date /*+ indexnl */ = D )
 SELECT  COUNT(*);
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-3/query2.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-3/query2.sqlpp
index 09b187e..badd2cb 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-3/query2.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-3/query2.sqlpp
@@ -42,8 +42,7 @@
 CREATE INDEX IdxYelpCheckinDates ON YelpCheckin (UNNEST checkin_times SELECT date);
 
 FROM    YelpCheckinDateMarkers M, YelpCheckin C
-WHERE   ( EVERY D IN C.checkin_times
+WHERE   ( SOME AND EVERY D IN C.checkin_times
           SATISFIES D.date /*+ indexnl */ = M.date ) AND
-        LEN (C.checkin_times) > 0 AND
         C.business_id = "--Ni3oJ4VOqfOEu7Sj2Vzg"
 SELECT  COUNT(*);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-4/query3.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-4/query3.sqlpp
index 39e2672..da8a388 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-4/query3.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-4/query3.sqlpp
@@ -43,10 +43,8 @@
 CREATE INDEX IdxYelpCheckinDates ON YelpCheckin (UNNEST checkin_times UNNEST dates);
 
 FROM    YelpCheckinDateMarkers M, YelpCheckin C
-WHERE   ( EVERY CT IN C.checkin_times
-          SATISFIES ( EVERY D IN CT.dates
-                      SATISFIES D /*+ indexnl */ = M.date ) AND
-                    LEN (CT.dates) > 0 ) AND
-        LEN (C.checkin_times) > 0 AND
+WHERE   ( SOME AND EVERY CT IN C.checkin_times
+          SATISFIES ( SOME AND EVERY D IN CT.dates
+                      SATISFIES D /*+ indexnl */ = M.date ) ) AND
         C.business_id = "--Ni3oJ4VOqfOEu7Sj2Vzg"
 SELECT  COUNT(*);
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-4/query4.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-4/query4.sqlpp
index 6f555f9..cf1ea46 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-4/query4.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/join-quantified-queries/use-case-4/query4.sqlpp
@@ -45,14 +45,10 @@
 CREATE INDEX IdxYelpCheckinDatesB ON YelpCheckinB (UNNEST checkin_times UNNEST dates);
 
 FROM    YelpCheckinDateMarkers M, YelpCheckinA A, YelpCheckinB B
-WHERE   ( EVERY CT IN A.checkin_times
-          SATISFIES ( EVERY D IN CT.dates
-                      SATISFIES D /*+ indexnl */ = M.date ) AND
-                    LEN (CT.dates) > 0 ) AND
-        LEN (A.checkin_times) > 0 AND
-        ( EVERY CT IN B.checkin_times
-          SATISFIES ( EVERY D IN CT.dates
-                      SATISFIES D /*+ indexnl */ = M.date ) AND
-                    LEN (CT.dates) > 0 ) AND
-        LEN (B.checkin_times) > 0
+WHERE   ( SOME AND EVERY CT IN A.checkin_times
+          SATISFIES SOME AND EVERY D IN CT.dates
+                    SATISFIES D /*+ indexnl */ = M.date ) AND
+        ( SOME AND EVERY CT IN B.checkin_times
+          SATISFIES SOME AND EVERY D IN CT.dates
+                    SATISFIES D /*+ indexnl */ = M.date )
 SELECT  COUNT(*);
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/multiple-quantifiers/query7.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/multiple-quantifiers/query7.sqlpp
new file mode 100644
index 0000000..cbef4a7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/multiple-quantifiers/query7.sqlpp
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+SET               `compiler.arrayindex` "true";
+
+DROP DATAVERSE    TestDataverse IF EXISTS;
+CREATE DATAVERSE  TestDataverse;
+USE               TestDataverse;
+
+CREATE TYPE       TestType AS {
+    _id: uuid,
+    items: [{
+        item: bigint
+    }]
+};
+CREATE DATASET    Dataset1 (TestType)
+PRIMARY KEY        _id AUTOGENERATED;
+CREATE INDEX      d1Idx
+ON                Dataset1 ( UNNEST items
+                             SELECT item );
+
+-- Single UNNEST w/ SELECT, closed index.
+FROM       Dataset1 D1
+WHERE      SOME AND EVERY I IN D1.items, J IN D1.other_items
+           SATISFIES I.item = 1 AND J.item = 2
+SELECT     *;
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/multiple-quantifiers/query8.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/multiple-quantifiers/query8.sqlpp
new file mode 100644
index 0000000..27080e4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/multiple-quantifiers/query8.sqlpp
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+SET               `compiler.arrayindex` "true";
+
+DROP DATAVERSE    TestDataverse IF EXISTS;
+CREATE DATAVERSE  TestDataverse;
+USE               TestDataverse;
+
+CREATE TYPE       TestType AS {
+    _id: uuid,
+    outer_items: [{
+        inner_items: [{
+            item: bigint
+        }]
+    }]
+};
+CREATE DATASET    Dataset1 (TestType)
+PRIMARY KEY        _id AUTOGENERATED;
+CREATE INDEX      d1Idx
+ON                Dataset1 ( UNNEST outer_items
+                             UNNEST inner_items
+                             SELECT item );
+
+-- Double UNNEST w/ SELECT, open index.
+FROM       Dataset1 D1
+WHERE      SOME AND EVERY I1 IN D1.outer_items, J IN D1.other_items
+           SATISFIES J.item = 2 AND ( SOME AND EVERY I2 IN I1.inner_items, J2 IN I1.other_inner_items
+                                      SATISFIES I2.item = 1 AND J2.item = 2 )
+SELECT     *;
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-1/query4.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-1/query4.sqlpp
new file mode 100644
index 0000000..0fa7d07
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-1/query4.sqlpp
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+SET `compiler.arrayindex` "true";
+
+DROP DATAVERSE TestYelp IF EXISTS;
+CREATE DATAVERSE TestYelp;
+USE TestYelp;
+
+CREATE TYPE CheckinType AS {
+    checkin_id: uuid,
+    business_id: string,
+    dates: [string]
+};
+
+CREATE DATASET YelpCheckin(CheckinType) PRIMARY KEY checkin_id AUTOGENERATED;
+CREATE INDEX IdxYelpCheckinDates ON YelpCheckin (UNNEST dates);
+
+SELECT COUNT(*)
+FROM YelpCheckin C
+WHERE SOME AND EVERY D IN C.dates
+      SATISFIES D > "2016" AND D < "2017";
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-2/query3.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-2/query3.sqlpp
index 24ae2e4..0a08372 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-2/query3.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-2/query3.sqlpp
@@ -36,6 +36,5 @@
 
 SELECT COUNT(*)
 FROM YelpCheckin C
-WHERE LEN(C.checkin_times.dates) > 0 AND
-      (EVERY D IN C.checkin_times.dates
-       SATISFIES D > "2016" AND D < "2017");
+WHERE SOME AND EVERY D IN C.checkin_times.dates
+      SATISFIES D > "2016" AND D < "2017";
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-3/query3.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-3/query3.sqlpp
index 52f533d..d1fe997 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-3/query3.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-3/query3.sqlpp
@@ -36,6 +36,5 @@
 
 SELECT C.business_id
 FROM YelpCheckin C
-WHERE LEN(C.checkin_times) > 0 AND
-      (EVERY D IN C.checkin_times
-       SATISFIES D.date BETWEEN "2016" AND "2017");
+WHERE SOME AND EVERY D IN C.checkin_times
+      SATISFIES D.date BETWEEN "2016" AND "2017";
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-4/query3.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-4/query3.sqlpp
index b4ffe06..160805a 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-4/query3.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-4/query3.sqlpp
@@ -36,9 +36,8 @@
 
 SELECT C.business_id
 FROM YelpCheckin C
-WHERE LEN(C.checkin_times) > 0 AND
-      (EVERY CT IN C.checkin_times
-       SATISFIES (
+WHERE SOME AND EVERY CT IN C.checkin_times
+      SATISFIES (
            SOME D IN CT.dates
            SATISFIES "2019-06-07" = D
-      ));
\ No newline at end of file
+      );
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-4/query4.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-4/query4.sqlpp
index 1cadb11..4d094a1 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-4/query4.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-4/query4.sqlpp
@@ -35,9 +35,7 @@
 CREATE INDEX IdxYelpCheckinDates ON YelpCheckin (UNNEST checkin_times UNNEST dates);
 
 FROM    YelpCheckin C
-WHERE   LEN(C.checkin_times) > 0 AND
-        ( SOME CT IN C.checkin_times
-          SATISFIES ( LEN(CT.dates) > 0 AND
-                      ( EVERY D IN CT.dates
-                        SATISFIES D > "2019-06-07" ) ) )
+WHERE   SOME CT IN C.checkin_times
+        SATISFIES SOME AND EVERY D IN CT.dates
+                  SATISFIES D > "2019-06-07"
 SELECT  C.business_id;
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-4/query5.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-4/query5.sqlpp
index b27e7b0..e63747f 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-4/query5.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/array-index/select-quantified-queries/use-case-4/query5.sqlpp
@@ -35,9 +35,7 @@
 CREATE INDEX IdxYelpCheckinDates ON YelpCheckin (UNNEST checkin_times UNNEST dates);
 
 FROM    YelpCheckin C
-WHERE   LEN(C.checkin_times) > 0 AND
-        ( EVERY CT IN C.checkin_times
-          SATISFIES ( LEN(CT.dates) > 0 AND
-                      ( EVERY D IN CT.dates
-                        SATISFIES D > "2019-06-07" ) ) )
+WHERE   SOME AND EVERY CT IN C.checkin_times
+        SATISFIES SOME AND EVERY D IN CT.dates
+                  SATISFIES D > "2019-06-07"
 SELECT  C.business_id;
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-1/query5.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-1/query5.plan
new file mode 100644
index 0000000..e06e50b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-1/query5.plan
@@ -0,0 +1,38 @@
+-- DISTRIBUTE_RESULT  |UNPARTITIONED|
+  -- ONE_TO_ONE_EXCHANGE  |UNPARTITIONED|
+    -- STREAM_PROJECT  |UNPARTITIONED|
+      -- ASSIGN  |UNPARTITIONED|
+        -- AGGREGATE  |UNPARTITIONED|
+          -- RANDOM_MERGE_EXCHANGE  |PARTITIONED|
+            -- AGGREGATE  |PARTITIONED|
+              -- STREAM_SELECT  |PARTITIONED|
+                -- STREAM_PROJECT  |PARTITIONED|
+                  -- SUBPLAN  |PARTITIONED|
+                          {
+                            -- AGGREGATE  |LOCAL|
+                              -- UNNEST  |LOCAL|
+                                -- NESTED_TUPLE_SOURCE  |LOCAL|
+                          }
+                    -- STREAM_PROJECT  |PARTITIONED|
+                      -- STREAM_SELECT  |PARTITIONED|
+                        -- ASSIGN  |PARTITIONED|
+                          -- STREAM_PROJECT  |PARTITIONED|
+                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                              -- BTREE_SEARCH (TestYelp.YelpCheckin.YelpCheckin)  |PARTITIONED|
+                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                  -- STREAM_PROJECT  |PARTITIONED|
+                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                      -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                          -- STABLE_SORT [$$71(ASC), $$63(ASC)]  |PARTITIONED|
+                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                              -- STREAM_PROJECT  |PARTITIONED|
+                                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                  -- BTREE_SEARCH (TestYelp.YelpCheckin.IdxYelpCheckinDates)  |PARTITIONED|
+                                                    -- BROADCAST_EXCHANGE  |PARTITIONED|
+                                                      -- STREAM_PROJECT  |PARTITIONED|
+                                                        -- ASSIGN  |PARTITIONED|
+                                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                            -- DATASOURCE_SCAN (TestYelp.YelpCheckinDateMarkers)  |PARTITIONED|
+                                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-2/query2.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-2/query2.plan
index 4fa93b1..109cc05 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-2/query2.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-2/query2.plan
@@ -10,13 +10,12 @@
                   -- SUBPLAN  |PARTITIONED|
                           {
                             -- AGGREGATE  |LOCAL|
-                              -- STREAM_SELECT  |LOCAL|
-                                -- UNNEST  |LOCAL|
-                                  -- NESTED_TUPLE_SOURCE  |LOCAL|
+                              -- UNNEST  |LOCAL|
+                                -- NESTED_TUPLE_SOURCE  |LOCAL|
                           }
                     -- STREAM_PROJECT  |PARTITIONED|
-                      -- STREAM_SELECT  |PARTITIONED|
-                        -- ASSIGN  |PARTITIONED|
+                      -- ASSIGN  |PARTITIONED|
+                        -- STREAM_SELECT  |PARTITIONED|
                           -- STREAM_PROJECT  |PARTITIONED|
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                               -- BTREE_SEARCH (TestYelp.YelpCheckin.YelpCheckin)  |PARTITIONED|
@@ -25,7 +24,7 @@
                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                       -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          -- STABLE_SORT [$$76(ASC), $$66(ASC)]  |PARTITIONED|
+                                          -- STABLE_SORT [$$73(ASC), $$64(ASC)]  |PARTITIONED|
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                               -- STREAM_PROJECT  |PARTITIONED|
                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-3/query2.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-3/query2.plan
index 76e50bc..7217e9f 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-3/query2.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-3/query2.plan
@@ -10,10 +10,9 @@
                   -- SUBPLAN  |PARTITIONED|
                           {
                             -- AGGREGATE  |LOCAL|
-                              -- STREAM_SELECT  |LOCAL|
-                                -- ASSIGN  |LOCAL|
-                                  -- UNNEST  |LOCAL|
-                                    -- NESTED_TUPLE_SOURCE  |LOCAL|
+                              -- ASSIGN  |LOCAL|
+                                -- UNNEST  |LOCAL|
+                                  -- NESTED_TUPLE_SOURCE  |LOCAL|
                           }
                     -- STREAM_PROJECT  |PARTITIONED|
                       -- STREAM_SELECT  |PARTITIONED|
@@ -26,7 +25,7 @@
                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                       -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          -- STABLE_SORT [$$75(ASC), $$65(ASC)]  |PARTITIONED|
+                                          -- STABLE_SORT [$$73(ASC), $$64(ASC)]  |PARTITIONED|
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                               -- STREAM_PROJECT  |PARTITIONED|
                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-4/query3.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-4/query3.plan
index 7331734..6c55934 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-4/query3.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-4/query3.plan
@@ -10,17 +10,15 @@
                   -- SUBPLAN  |PARTITIONED|
                           {
                             -- AGGREGATE  |LOCAL|
-                              -- STREAM_SELECT  |LOCAL|
-                                -- SUBPLAN  |LOCAL|
-                                        {
-                                          -- AGGREGATE  |LOCAL|
-                                            -- STREAM_SELECT  |LOCAL|
-                                              -- UNNEST  |LOCAL|
-                                                -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                        }
-                                  -- ASSIGN  |LOCAL|
-                                    -- UNNEST  |LOCAL|
-                                      -- NESTED_TUPLE_SOURCE  |LOCAL|
+                              -- SUBPLAN  |LOCAL|
+                                      {
+                                        -- AGGREGATE  |LOCAL|
+                                          -- UNNEST  |LOCAL|
+                                            -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                      }
+                                -- ASSIGN  |LOCAL|
+                                  -- UNNEST  |LOCAL|
+                                    -- NESTED_TUPLE_SOURCE  |LOCAL|
                           }
                     -- STREAM_PROJECT  |PARTITIONED|
                       -- STREAM_SELECT  |PARTITIONED|
@@ -33,7 +31,7 @@
                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                       -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          -- STABLE_SORT [$$93(ASC), $$80(ASC)]  |PARTITIONED|
+                                          -- STABLE_SORT [$$88(ASC), $$77(ASC)]  |PARTITIONED|
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                               -- STREAM_PROJECT  |PARTITIONED|
                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-4/query4.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-4/query4.plan
index ad7b9c8..2719282 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-4/query4.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/join-quantified-queries/use-case-4/query4.plan
@@ -10,70 +10,64 @@
                   -- SUBPLAN  |PARTITIONED|
                           {
                             -- AGGREGATE  |LOCAL|
-                              -- STREAM_SELECT  |LOCAL|
-                                -- SUBPLAN  |LOCAL|
-                                        {
-                                          -- AGGREGATE  |LOCAL|
-                                            -- STREAM_SELECT  |LOCAL|
-                                              -- UNNEST  |LOCAL|
-                                                -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                        }
-                                  -- ASSIGN  |LOCAL|
-                                    -- UNNEST  |LOCAL|
-                                      -- NESTED_TUPLE_SOURCE  |LOCAL|
+                              -- SUBPLAN  |LOCAL|
+                                      {
+                                        -- AGGREGATE  |LOCAL|
+                                          -- UNNEST  |LOCAL|
+                                            -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                      }
+                                -- ASSIGN  |LOCAL|
+                                  -- UNNEST  |LOCAL|
+                                    -- NESTED_TUPLE_SOURCE  |LOCAL|
                           }
-                    -- STREAM_SELECT  |PARTITIONED|
-                      -- STREAM_PROJECT  |PARTITIONED|
-                        -- ASSIGN  |PARTITIONED|
-                          -- STREAM_PROJECT  |PARTITIONED|
-                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              -- BTREE_SEARCH (TestYelp.YelpCheckinB.YelpCheckinB)  |PARTITIONED|
-                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  -- STREAM_PROJECT  |PARTITIONED|
-                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
-                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          -- STABLE_SORT [$$144(ASC), $$122(ASC), $$123(ASC), $$97(ASC)]  |PARTITIONED|
-                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              -- STREAM_PROJECT  |PARTITIONED|
-                                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                  -- BTREE_SEARCH (TestYelp.YelpCheckinB.IdxYelpCheckinDatesB)  |PARTITIONED|
-                                                    -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                                      -- STREAM_SELECT  |PARTITIONED|
-                                                        -- STREAM_PROJECT  |PARTITIONED|
-                                                          -- SUBPLAN  |PARTITIONED|
-                                                                  {
-                                                                    -- AGGREGATE  |LOCAL|
-                                                                      -- STREAM_SELECT  |LOCAL|
-                                                                        -- SUBPLAN  |LOCAL|
-                                                                                {
-                                                                                  -- AGGREGATE  |LOCAL|
-                                                                                    -- STREAM_SELECT  |LOCAL|
-                                                                                      -- UNNEST  |LOCAL|
-                                                                                        -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                                                                }
-                                                                          -- ASSIGN  |LOCAL|
-                                                                            -- UNNEST  |LOCAL|
-                                                                              -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                                                  }
-                                                            -- STREAM_SELECT  |PARTITIONED|
+                    -- STREAM_PROJECT  |PARTITIONED|
+                      -- ASSIGN  |PARTITIONED|
+                        -- STREAM_PROJECT  |PARTITIONED|
+                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                            -- BTREE_SEARCH (TestYelp.YelpCheckinB.YelpCheckinB)  |PARTITIONED|
+                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                -- STREAM_PROJECT  |PARTITIONED|
+                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                    -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                        -- STABLE_SORT [$$134(ASC), $$116(ASC), $$117(ASC), $$95(ASC), $$96(ASC)]  |PARTITIONED|
+                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                            -- STREAM_PROJECT  |PARTITIONED|
+                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                -- BTREE_SEARCH (TestYelp.YelpCheckinB.IdxYelpCheckinDatesB)  |PARTITIONED|
+                                                  -- BROADCAST_EXCHANGE  |PARTITIONED|
+                                                    -- STREAM_SELECT  |PARTITIONED|
+                                                      -- STREAM_PROJECT  |PARTITIONED|
+                                                        -- SUBPLAN  |PARTITIONED|
+                                                                {
+                                                                  -- AGGREGATE  |LOCAL|
+                                                                    -- SUBPLAN  |LOCAL|
+                                                                            {
+                                                                              -- AGGREGATE  |LOCAL|
+                                                                                -- UNNEST  |LOCAL|
+                                                                                  -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                                                            }
+                                                                      -- ASSIGN  |LOCAL|
+                                                                        -- UNNEST  |LOCAL|
+                                                                          -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                                                }
+                                                          -- STREAM_PROJECT  |PARTITIONED|
+                                                            -- ASSIGN  |PARTITIONED|
                                                               -- STREAM_PROJECT  |PARTITIONED|
-                                                                -- ASSIGN  |PARTITIONED|
-                                                                  -- STREAM_PROJECT  |PARTITIONED|
+                                                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                  -- BTREE_SEARCH (TestYelp.YelpCheckinA.YelpCheckinA)  |PARTITIONED|
                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                      -- BTREE_SEARCH (TestYelp.YelpCheckinA.YelpCheckinA)  |PARTITIONED|
+                                                                      -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                          -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+                                                                          -- STABLE_SORT [$$132(ASC), $$116(ASC)]  |PARTITIONED|
                                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                              -- STABLE_SORT [$$142(ASC), $$122(ASC)]  |PARTITIONED|
+                                                                              -- STREAM_PROJECT  |PARTITIONED|
                                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                  -- STREAM_PROJECT  |PARTITIONED|
-                                                                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                      -- BTREE_SEARCH (TestYelp.YelpCheckinA.IdxYelpCheckinDatesA)  |PARTITIONED|
-                                                                                        -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                                                                          -- STREAM_PROJECT  |PARTITIONED|
-                                                                                            -- ASSIGN  |PARTITIONED|
+                                                                                  -- BTREE_SEARCH (TestYelp.YelpCheckinA.IdxYelpCheckinDatesA)  |PARTITIONED|
+                                                                                    -- BROADCAST_EXCHANGE  |PARTITIONED|
+                                                                                      -- STREAM_PROJECT  |PARTITIONED|
+                                                                                        -- ASSIGN  |PARTITIONED|
+                                                                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                                            -- DATASOURCE_SCAN (TestYelp.YelpCheckinDateMarkers)  |PARTITIONED|
                                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                -- DATASOURCE_SCAN (TestYelp.YelpCheckinDateMarkers)  |PARTITIONED|
-                                                                                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                    -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
\ No newline at end of file
+                                                                                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/multiple-quantifiers/query7.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/multiple-quantifiers/query7.plan
new file mode 100644
index 0000000..7999e77
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/multiple-quantifiers/query7.plan
@@ -0,0 +1,31 @@
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    -- STREAM_PROJECT  |PARTITIONED|
+      -- ASSIGN  |PARTITIONED|
+        -- STREAM_PROJECT  |PARTITIONED|
+          -- STREAM_SELECT  |PARTITIONED|
+            -- STREAM_PROJECT  |PARTITIONED|
+              -- SUBPLAN  |PARTITIONED|
+                      {
+                        -- AGGREGATE  |LOCAL|
+                          -- ASSIGN  |LOCAL|
+                            -- UNNEST  |LOCAL|
+                              -- ASSIGN  |LOCAL|
+                                -- UNNEST  |LOCAL|
+                                  -- NESTED_TUPLE_SOURCE  |LOCAL|
+                      }
+                -- ASSIGN  |PARTITIONED|
+                  -- STREAM_PROJECT  |PARTITIONED|
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      -- BTREE_SEARCH (TestDataverse.Dataset1.Dataset1)  |PARTITIONED|
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                              -- STABLE_SORT [$$52(ASC)]  |PARTITIONED|
+                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                  -- STREAM_PROJECT  |PARTITIONED|
+                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                      -- BTREE_SEARCH (TestDataverse.Dataset1.d1Idx)  |PARTITIONED|
+                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                          -- ASSIGN  |PARTITIONED|
+                                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/multiple-quantifiers/query8.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/multiple-quantifiers/query8.plan
new file mode 100644
index 0000000..cc99bbf
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/multiple-quantifiers/query8.plan
@@ -0,0 +1,40 @@
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    -- STREAM_PROJECT  |PARTITIONED|
+      -- ASSIGN  |PARTITIONED|
+        -- STREAM_PROJECT  |PARTITIONED|
+          -- STREAM_SELECT  |PARTITIONED|
+            -- STREAM_PROJECT  |PARTITIONED|
+              -- SUBPLAN  |PARTITIONED|
+                      {
+                        -- AGGREGATE  |LOCAL|
+                          -- SUBPLAN  |LOCAL|
+                                  {
+                                    -- AGGREGATE  |LOCAL|
+                                      -- ASSIGN  |LOCAL|
+                                        -- UNNEST  |LOCAL|
+                                          -- ASSIGN  |LOCAL|
+                                            -- UNNEST  |LOCAL|
+                                              -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                  }
+                            -- ASSIGN  |LOCAL|
+                              -- UNNEST  |LOCAL|
+                                -- ASSIGN  |LOCAL|
+                                  -- UNNEST  |LOCAL|
+                                    -- NESTED_TUPLE_SOURCE  |LOCAL|
+                      }
+                -- ASSIGN  |PARTITIONED|
+                  -- STREAM_PROJECT  |PARTITIONED|
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      -- BTREE_SEARCH (TestDataverse.Dataset1.Dataset1)  |PARTITIONED|
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                              -- STABLE_SORT [$$85(ASC)]  |PARTITIONED|
+                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                  -- STREAM_PROJECT  |PARTITIONED|
+                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                      -- BTREE_SEARCH (TestDataverse.Dataset1.d1Idx)  |PARTITIONED|
+                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                          -- ASSIGN  |PARTITIONED|
+                                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-1/query4.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-1/query4.plan
new file mode 100644
index 0000000..1ed6cd6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-1/query4.plan
@@ -0,0 +1,31 @@
+-- DISTRIBUTE_RESULT  |UNPARTITIONED|
+  -- ONE_TO_ONE_EXCHANGE  |UNPARTITIONED|
+    -- STREAM_PROJECT  |UNPARTITIONED|
+      -- ASSIGN  |UNPARTITIONED|
+        -- AGGREGATE  |UNPARTITIONED|
+          -- RANDOM_MERGE_EXCHANGE  |PARTITIONED|
+            -- AGGREGATE  |PARTITIONED|
+              -- STREAM_SELECT  |PARTITIONED|
+                -- STREAM_PROJECT  |PARTITIONED|
+                  -- SUBPLAN  |PARTITIONED|
+                          {
+                            -- AGGREGATE  |LOCAL|
+                              -- UNNEST  |LOCAL|
+                                -- NESTED_TUPLE_SOURCE  |LOCAL|
+                          }
+                    -- STREAM_PROJECT  |PARTITIONED|
+                      -- ASSIGN  |PARTITIONED|
+                        -- STREAM_PROJECT  |PARTITIONED|
+                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                            -- BTREE_SEARCH (TestYelp.YelpCheckin.YelpCheckin)  |PARTITIONED|
+                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                    -- STABLE_SORT [$$57(ASC)]  |PARTITIONED|
+                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                        -- STREAM_PROJECT  |PARTITIONED|
+                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                            -- BTREE_SEARCH (TestYelp.YelpCheckin.IdxYelpCheckinDates)  |PARTITIONED|
+                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                -- ASSIGN  |PARTITIONED|
+                                                  -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-2/query3.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-2/query3.plan
index b9e4c18..10ad036 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-2/query3.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-2/query3.plan
@@ -10,24 +10,22 @@
                   -- SUBPLAN  |PARTITIONED|
                           {
                             -- AGGREGATE  |LOCAL|
-                              -- STREAM_SELECT  |LOCAL|
-                                -- UNNEST  |LOCAL|
-                                  -- NESTED_TUPLE_SOURCE  |LOCAL|
+                              -- UNNEST  |LOCAL|
+                                -- NESTED_TUPLE_SOURCE  |LOCAL|
                           }
-                    -- STREAM_SELECT  |PARTITIONED|
-                      -- STREAM_PROJECT  |PARTITIONED|
-                        -- ASSIGN  |PARTITIONED|
-                          -- STREAM_PROJECT  |PARTITIONED|
-                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              -- BTREE_SEARCH (TestYelp.YelpCheckin.YelpCheckin)  |PARTITIONED|
-                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
-                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      -- STABLE_SORT [$$63(ASC)]  |PARTITIONED|
-                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          -- STREAM_PROJECT  |PARTITIONED|
-                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              -- BTREE_SEARCH (TestYelp.YelpCheckin.IdxYelpCheckinDates)  |PARTITIONED|
-                                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                  -- ASSIGN  |PARTITIONED|
-                                                    -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                    -- STREAM_PROJECT  |PARTITIONED|
+                      -- ASSIGN  |PARTITIONED|
+                        -- STREAM_PROJECT  |PARTITIONED|
+                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                            -- BTREE_SEARCH (TestYelp.YelpCheckin.YelpCheckin)  |PARTITIONED|
+                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                    -- STABLE_SORT [$$59(ASC)]  |PARTITIONED|
+                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                        -- STREAM_PROJECT  |PARTITIONED|
+                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                            -- BTREE_SEARCH (TestYelp.YelpCheckin.IdxYelpCheckinDates)  |PARTITIONED|
+                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                -- ASSIGN  |PARTITIONED|
+                                                  -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-3/query3.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-3/query3.plan
index f8aad44..2fb6ed5 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-3/query3.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-3/query3.plan
@@ -8,25 +8,23 @@
               -- SUBPLAN  |PARTITIONED|
                       {
                         -- AGGREGATE  |LOCAL|
-                          -- STREAM_SELECT  |LOCAL|
-                            -- ASSIGN  |LOCAL|
-                              -- UNNEST  |LOCAL|
-                                -- NESTED_TUPLE_SOURCE  |LOCAL|
+                          -- ASSIGN  |LOCAL|
+                            -- UNNEST  |LOCAL|
+                              -- NESTED_TUPLE_SOURCE  |LOCAL|
                       }
-                -- STREAM_SELECT  |PARTITIONED|
-                  -- STREAM_PROJECT  |PARTITIONED|
-                    -- ASSIGN  |PARTITIONED|
-                      -- STREAM_PROJECT  |PARTITIONED|
-                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          -- BTREE_SEARCH (TestYelp.YelpCheckin.YelpCheckin)  |PARTITIONED|
-                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
-                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  -- STABLE_SORT [$$44(ASC)]  |PARTITIONED|
-                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      -- STREAM_PROJECT  |PARTITIONED|
-                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          -- BTREE_SEARCH (TestYelp.YelpCheckin.IdxYelpCheckinDates)  |PARTITIONED|
-                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              -- ASSIGN  |PARTITIONED|
-                                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                -- STREAM_PROJECT  |PARTITIONED|
+                  -- ASSIGN  |PARTITIONED|
+                    -- STREAM_PROJECT  |PARTITIONED|
+                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                        -- BTREE_SEARCH (TestYelp.YelpCheckin.YelpCheckin)  |PARTITIONED|
+                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                            -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                -- STABLE_SORT [$$42(ASC)]  |PARTITIONED|
+                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                    -- STREAM_PROJECT  |PARTITIONED|
+                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                        -- BTREE_SEARCH (TestYelp.YelpCheckin.IdxYelpCheckinDates)  |PARTITIONED|
+                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                            -- ASSIGN  |PARTITIONED|
+                                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-4/query3.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-4/query3.plan
index bfdc30a..8de78d4 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-4/query3.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-4/query3.plan
@@ -8,32 +8,30 @@
               -- SUBPLAN  |PARTITIONED|
                       {
                         -- AGGREGATE  |LOCAL|
-                          -- STREAM_SELECT  |LOCAL|
-                            -- SUBPLAN  |LOCAL|
-                                    {
-                                      -- AGGREGATE  |LOCAL|
-                                        -- STREAM_SELECT  |LOCAL|
-                                          -- UNNEST  |LOCAL|
-                                            -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                    }
-                              -- ASSIGN  |LOCAL|
-                                -- UNNEST  |LOCAL|
-                                  -- NESTED_TUPLE_SOURCE  |LOCAL|
+                          -- SUBPLAN  |LOCAL|
+                                  {
+                                    -- AGGREGATE  |LOCAL|
+                                      -- STREAM_SELECT  |LOCAL|
+                                        -- UNNEST  |LOCAL|
+                                          -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                  }
+                            -- ASSIGN  |LOCAL|
+                              -- UNNEST  |LOCAL|
+                                -- NESTED_TUPLE_SOURCE  |LOCAL|
                       }
-                -- STREAM_SELECT  |PARTITIONED|
-                  -- STREAM_PROJECT  |PARTITIONED|
-                    -- ASSIGN  |PARTITIONED|
-                      -- STREAM_PROJECT  |PARTITIONED|
-                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          -- BTREE_SEARCH (TestYelp.YelpCheckin.YelpCheckin)  |PARTITIONED|
-                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
-                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  -- STABLE_SORT [$$54(ASC)]  |PARTITIONED|
-                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      -- STREAM_PROJECT  |PARTITIONED|
-                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          -- BTREE_SEARCH (TestYelp.YelpCheckin.IdxYelpCheckinDates)  |PARTITIONED|
-                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              -- ASSIGN  |PARTITIONED|
-                                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                -- STREAM_PROJECT  |PARTITIONED|
+                  -- ASSIGN  |PARTITIONED|
+                    -- STREAM_PROJECT  |PARTITIONED|
+                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                        -- BTREE_SEARCH (TestYelp.YelpCheckin.YelpCheckin)  |PARTITIONED|
+                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                            -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                -- STABLE_SORT [$$51(ASC)]  |PARTITIONED|
+                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                    -- STREAM_PROJECT  |PARTITIONED|
+                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                        -- BTREE_SEARCH (TestYelp.YelpCheckin.IdxYelpCheckinDates)  |PARTITIONED|
+                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                            -- ASSIGN  |PARTITIONED|
+                                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-4/query4.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-4/query4.plan
index 2f44d43..10b415f 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-4/query4.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-4/query4.plan
@@ -12,29 +12,26 @@
                             -- SUBPLAN  |LOCAL|
                                     {
                                       -- AGGREGATE  |LOCAL|
-                                        -- STREAM_SELECT  |LOCAL|
-                                          -- UNNEST  |LOCAL|
-                                            -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                        -- UNNEST  |LOCAL|
+                                          -- NESTED_TUPLE_SOURCE  |LOCAL|
                                     }
-                              -- STREAM_SELECT  |LOCAL|
-                                -- ASSIGN  |LOCAL|
-                                  -- UNNEST  |LOCAL|
-                                    -- NESTED_TUPLE_SOURCE  |LOCAL|
+                              -- ASSIGN  |LOCAL|
+                                -- UNNEST  |LOCAL|
+                                  -- NESTED_TUPLE_SOURCE  |LOCAL|
                       }
-                -- STREAM_SELECT  |PARTITIONED|
-                  -- STREAM_PROJECT  |PARTITIONED|
-                    -- ASSIGN  |PARTITIONED|
-                      -- STREAM_PROJECT  |PARTITIONED|
-                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          -- BTREE_SEARCH (TestYelp.YelpCheckin.YelpCheckin)  |PARTITIONED|
-                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
-                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  -- STABLE_SORT [$$58(ASC)]  |PARTITIONED|
-                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      -- STREAM_PROJECT  |PARTITIONED|
-                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          -- BTREE_SEARCH (TestYelp.YelpCheckin.IdxYelpCheckinDates)  |PARTITIONED|
-                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              -- ASSIGN  |PARTITIONED|
-                                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                -- STREAM_PROJECT  |PARTITIONED|
+                  -- ASSIGN  |PARTITIONED|
+                    -- STREAM_PROJECT  |PARTITIONED|
+                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                        -- BTREE_SEARCH (TestYelp.YelpCheckin.YelpCheckin)  |PARTITIONED|
+                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                            -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                -- STABLE_SORT [$$50(ASC)]  |PARTITIONED|
+                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                    -- STREAM_PROJECT  |PARTITIONED|
+                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                        -- BTREE_SEARCH (TestYelp.YelpCheckin.IdxYelpCheckinDates)  |PARTITIONED|
+                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                            -- ASSIGN  |PARTITIONED|
+                                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-4/query5.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-4/query5.plan
index 0f3a84c..f1c1609 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-4/query5.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/array-index/select-quantified-queries/use-case-4/query5.plan
@@ -8,32 +8,29 @@
               -- SUBPLAN  |PARTITIONED|
                       {
                         -- AGGREGATE  |LOCAL|
-                          -- STREAM_SELECT  |LOCAL|
-                            -- SUBPLAN  |LOCAL|
-                                    {
-                                      -- AGGREGATE  |LOCAL|
-                                        -- STREAM_SELECT  |LOCAL|
-                                          -- UNNEST  |LOCAL|
-                                            -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                    }
-                              -- ASSIGN  |LOCAL|
-                                -- UNNEST  |LOCAL|
-                                  -- NESTED_TUPLE_SOURCE  |LOCAL|
+                          -- SUBPLAN  |LOCAL|
+                                  {
+                                    -- AGGREGATE  |LOCAL|
+                                      -- UNNEST  |LOCAL|
+                                        -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                  }
+                            -- ASSIGN  |LOCAL|
+                              -- UNNEST  |LOCAL|
+                                -- NESTED_TUPLE_SOURCE  |LOCAL|
                       }
-                -- STREAM_SELECT  |PARTITIONED|
-                  -- STREAM_PROJECT  |PARTITIONED|
-                    -- ASSIGN  |PARTITIONED|
-                      -- STREAM_PROJECT  |PARTITIONED|
-                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          -- BTREE_SEARCH (TestYelp.YelpCheckin.YelpCheckin)  |PARTITIONED|
-                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
-                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  -- STABLE_SORT [$$58(ASC)]  |PARTITIONED|
-                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      -- STREAM_PROJECT  |PARTITIONED|
-                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          -- BTREE_SEARCH (TestYelp.YelpCheckin.IdxYelpCheckinDates)  |PARTITIONED|
-                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              -- ASSIGN  |PARTITIONED|
-                                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                -- STREAM_PROJECT  |PARTITIONED|
+                  -- ASSIGN  |PARTITIONED|
+                    -- STREAM_PROJECT  |PARTITIONED|
+                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                        -- BTREE_SEARCH (TestYelp.YelpCheckin.YelpCheckin)  |PARTITIONED|
+                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                            -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
+                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                -- STABLE_SORT [$$52(ASC)]  |PARTITIONED|
+                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                    -- STREAM_PROJECT  |PARTITIONED|
+                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                        -- BTREE_SEARCH (TestYelp.YelpCheckin.IdxYelpCheckinDates)  |PARTITIONED|
+                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                            -- ASSIGN  |PARTITIONED|
+                                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-1/use-case-1.7.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-1/use-case-1.7.query.sqlpp
new file mode 100644
index 0000000..89e3a82
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-1/use-case-1.7.query.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+SET `compiler.arrayindex` "true";
+USE TestYelp;
+
+FROM      YelpCheckinDateMarkers M, YelpCheckinA A
+WHERE     SOME AND EVERY D IN A.dates
+          SATISFIES M.datetime /*+ indexnl */ = D
+SELECT    M.marker, A.business_id
+ORDER BY  M.marker, A.business_id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-2/use-case-2.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-2/use-case-2.4.query.sqlpp
index 6cd541c..4f641ed 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-2/use-case-2.4.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-2/use-case-2.4.query.sqlpp
@@ -20,8 +20,7 @@
 USE TestYelp;
 
 FROM      YelpCheckinDateMarkers M, YelpCheckinA A
-WHERE     LEN(A.checkin_times.dates) > 0 AND
-          ( EVERY D IN A.checkin_times.dates
-            SATISFIES M.date /*+ indexnl */ = D )
+WHERE     SOME AND EVERY D IN A.checkin_times.dates
+          SATISFIES M.date /*+ indexnl */ = D
 SELECT    M.marker, A.business_id
 ORDER BY  M.marker, A.business_id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-3/use-case-3.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-3/use-case-3.3.query.sqlpp
index 48f8660..1bd6236 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-3/use-case-3.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-3/use-case-3.3.query.sqlpp
@@ -20,7 +20,7 @@
 USE TestYelp;
 
 FROM     YelpCheckinDateMarkers M, YelpCheckin C
-WHERE    ( SOME D IN C.checkin_times
-           SATISFIES D.date /*+ indexnl */ = M.date )
+WHERE    SOME D IN C.checkin_times
+         SATISFIES D.date /*+ indexnl */ = M.date
 SELECT   M.marker, C.business_id
 ORDER BY M.marker, C.business_id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-3/use-case-3.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-3/use-case-3.4.query.sqlpp
index d933cb2..54a0bc4 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-3/use-case-3.4.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-3/use-case-3.4.query.sqlpp
@@ -20,8 +20,7 @@
 USE TestYelp;
 
 FROM     YelpCheckinDateMarkers M, YelpCheckin C
-WHERE    ( EVERY D IN C.checkin_times
-           SATISFIES D.date /*+ indexnl */ = M.date ) AND
-         LEN (C.checkin_times) > 0
+WHERE    SOME AND EVERY D IN C.checkin_times
+         SATISFIES D.date /*+ indexnl */ = M.date
 SELECT   M.marker, C.business_id
 ORDER BY M.marker, C.business_id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-4/use-case-4.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-4/use-case-4.3.query.sqlpp
index c349477..6bcb7a0 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-4/use-case-4.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-4/use-case-4.3.query.sqlpp
@@ -20,8 +20,8 @@
 USE TestYelp;
 
 FROM     YelpCheckinDateMarkers M, YelpCheckinA A
-WHERE    ( SOME CT IN A.checkin_times
-          SATISFIES ( SOME D IN CT.dates
-                      SATISFIES D /*+ indexnl */ = M.date ) )
+WHERE    SOME CT IN A.checkin_times
+         SATISFIES ( SOME D IN CT.dates
+                     SATISFIES D /*+ indexnl */ = M.date )
 SELECT   M.marker, A.business_id
 ORDER BY M.marker, A.business_id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-4/use-case-4.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-4/use-case-4.4.query.sqlpp
index b5338c8..ffaf276 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-4/use-case-4.4.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-4/use-case-4.4.query.sqlpp
@@ -20,9 +20,8 @@
 USE TestYelp;
 
 FROM     YelpCheckinDateMarkers M, YelpCheckinA A
-WHERE    ( EVERY CT IN A.checkin_times
-           SATISFIES ( SOME D IN CT.dates
-                       SATISFIES D /*+ indexnl */ = M.date ) ) AND
-         LEN (A.checkin_times) > 0
+WHERE    SOME AND EVERY CT IN A.checkin_times
+         SATISFIES ( SOME D IN CT.dates
+                     SATISFIES D /*+ indexnl */ = M.date )
 SELECT   M.marker, A.business_id
 ORDER BY M.marker, A.business_id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-4/use-case-4.5.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-4/use-case-4.5.query.sqlpp
index 70ec139..a37d923 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-4/use-case-4.5.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-4/use-case-4.5.query.sqlpp
@@ -20,10 +20,8 @@
 USE TestYelp;
 
 FROM     YelpCheckinDateMarkers M, YelpCheckinA A
-WHERE    ( EVERY CT IN A.checkin_times
-           SATISFIES ( EVERY D IN CT.dates
-                       SATISFIES D /*+ indexnl */ = M.date ) AND
-                     LEN (CT.dates) > 0 ) AND
-         LEN (A.checkin_times) > 0
+WHERE    SOME AND EVERY CT IN A.checkin_times
+         SATISFIES ( SOME AND EVERY D IN CT.dates
+                     SATISFIES D /*+ indexnl */ = M.date )
 SELECT   M.marker, A.business_id
 ORDER BY M.marker, A.business_id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-4/use-case-4.6.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-4/use-case-4.6.query.sqlpp
index 1522959..bf5e128 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-4/use-case-4.6.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/join-quantified-queries/use-case-4/use-case-4.6.query.sqlpp
@@ -21,15 +21,11 @@
 USE TestYelp;
 
 FROM     YelpCheckinDateMarkers M, YelpCheckinA A, YelpCheckinB B
-WHERE    ( EVERY CT IN A.checkin_times
-           SATISFIES ( EVERY D IN CT.dates
-                       SATISFIES D /*+ indexnl */ = M.date ) AND
-                     LEN (CT.dates) > 0 ) AND
-         LEN (A.checkin_times) > 0 AND
-         ( EVERY CT IN B.checkin_times
-           SATISFIES ( EVERY D IN CT.dates
-                       SATISFIES D /*+ indexnl */ = M.date ) AND
-                     LEN (CT.dates) > 0 ) AND
-         LEN (B.checkin_times) > 0
+WHERE    ( SOME AND EVERY CT IN A.checkin_times
+           SATISFIES ( SOME AND EVERY D IN CT.dates
+                       SATISFIES D /*+ indexnl */ = M.date ) ) AND
+         ( SOME AND EVERY CT IN B.checkin_times
+           SATISFIES ( SOME AND EVERY D IN CT.dates
+                       SATISFIES D /*+ indexnl */ = M.date ) )
 SELECT   M.marker, A.business_id AS business_id_a, B.business_id AS business_id_b
 ORDER BY M.marker, A.business_id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-1/use-case-1.7.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-1/use-case-1.7.query.sqlpp
new file mode 100644
index 0000000..a8eb5bc
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-1/use-case-1.7.query.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+SET `compiler.arrayindex` "true";
+
+USE TestYelp;
+
+FROM    YelpCheckin C
+WHERE   SOME AND EVERY D IN C.dates
+        SATISFIES D > "2016" AND D < "2017"
+SELECT  COUNT(*);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-2/use-case-2.6.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-2/use-case-2.6.query.sqlpp
index 86e3d9f..173f02c 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-2/use-case-2.6.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-2/use-case-2.6.query.sqlpp
@@ -21,7 +21,6 @@
 USE TestYelp;
 
 FROM    YelpCheckin C
-WHERE   LEN(C.checkin_times.dates) > 0 AND
-        ( EVERY D IN C.checkin_times.dates
-          SATISFIES D > "2016" AND D < "2017" )
+WHERE   SOME AND EVERY D IN C.checkin_times.dates
+        SATISFIES D > "2016" AND D < "2017"
 SELECT  COUNT(*);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-3/use-case-3.6.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-3/use-case-3.6.query.sqlpp
index f55fa3c..40b2ab4 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-3/use-case-3.6.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-3/use-case-3.6.query.sqlpp
@@ -21,7 +21,6 @@
 USE TestYelp;
 
 FROM    YelpCheckin C
-WHERE   LEN(C.checkin_times) > 0 AND
-        ( EVERY D IN C.checkin_times
-          SATISFIES D.date > "2016" AND D.date < "2017" )
+WHERE   SOME AND EVERY D IN C.checkin_times
+        SATISFIES D.date > "2016" AND D.date < "2017"
 SELECT  C.business_id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-4/use-case-4.6.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-4/use-case-4.6.query.sqlpp
index c4bb9a1..1035a86 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-4/use-case-4.6.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-4/use-case-4.6.query.sqlpp
@@ -21,8 +21,7 @@
 USE TestYelp;
 
 FROM    YelpCheckin C
-WHERE   LEN(C.checkin_times) > 0 AND
-        ( EVERY CT IN C.checkin_times
-          SATISFIES ( SOME D IN CT.dates
-                      SATISFIES "2019-06-07" = D ) )
+WHERE   SOME AND EVERY CT IN C.checkin_times
+        SATISFIES ( SOME D IN CT.dates
+                    SATISFIES "2019-06-07" = D )
 SELECT  C.business_id;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-4/use-case-4.7.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-4/use-case-4.7.query.sqlpp
index da9da19..a60a21e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-4/use-case-4.7.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/use-case-4/use-case-4.7.query.sqlpp
@@ -21,9 +21,7 @@
 USE TestYelp;
 
 FROM    YelpCheckin C
-WHERE   LEN(C.checkin_times) > 0 AND
-        ( EVERY CT IN C.checkin_times
-          SATISFIES ( LEN(CT.dates) > 0 AND
-                      ( EVERY D IN CT.dates
-                        SATISFIES D > "2019-06-05" ) ) )
+WHERE   SOME AND EVERY CT IN C.checkin_times
+        SATISFIES ( SOME AND EVERY D IN CT.dates
+                    SATISFIES D > "2019-06-05" )
 SELECT  C.business_id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/with-composite-pk/with-composite-pk.6.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/with-composite-pk/with-composite-pk.6.query.sqlpp
index 803aa44..90bec06 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/with-composite-pk/with-composite-pk.6.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/with-composite-pk/with-composite-pk.6.query.sqlpp
@@ -21,7 +21,6 @@
 USE TestYelp;
 
 FROM    YelpCheckin C
-WHERE   LEN(C.dates) > 0 AND
-        ( EVERY D IN C.dates
-          SATISFIES D > "2016" AND D < "2017" )
+WHERE   SOME AND EVERY D IN C.dates
+        SATISFIES D > "2016" AND D < "2017"
 SELECT  COUNT(*);
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/with-open-index/with-open-index.6.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/with-open-index/with-open-index.6.query.sqlpp
index 5ccbf5d..a8eb5bc 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/with-open-index/with-open-index.6.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array-index/select-quantified-queries/with-open-index/with-open-index.6.query.sqlpp
@@ -21,7 +21,6 @@
 USE TestYelp;
 
 FROM    YelpCheckin C
-WHERE   LEN(C.dates) > 0 AND
-        ( EVERY D IN C.dates
-          SATISFIES D > "2016" AND D < "2017" )
+WHERE   SOME AND EVERY D IN C.dates
+        SATISFIES D > "2016" AND D < "2017"
 SELECT  COUNT(*);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/array-index/join-quantified-queries/use-case-1/use-case-1.5.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/array-index/join-quantified-queries/use-case-1/use-case-1.5.adm
new file mode 100644
index 0000000..7533447
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/array-index/join-quantified-queries/use-case-1/use-case-1.5.adm
@@ -0,0 +1,2 @@
+{ "marker": "4fa1e250-7a68-3adb-04ec-6569c36882f5", "business_id": "3" }
+{ "marker": "991ed2f7-3374-33a5-ee65-77f067848381", "business_id": "3" }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/array-index/select-quantified-queries/use-case-1/use-case-1.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/array-index/select-quantified-queries/use-case-1/use-case-1.4.adm
new file mode 100644
index 0000000..7cc3573
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/array-index/select-quantified-queries/use-case-1/use-case-1.4.adm
@@ -0,0 +1 @@
+{ "$1": 1 }
diff --git a/asterixdb/asterix-doc/src/site/markdown/sqlpp/arrayindex.md b/asterixdb/asterix-doc/src/site/markdown/sqlpp/arrayindex.md
index 559e2d2..d91e48e 100644
--- a/asterixdb/asterix-doc/src/site/markdown/sqlpp/arrayindex.md
+++ b/asterixdb/asterix-doc/src/site/markdown/sqlpp/arrayindex.md
@@ -100,10 +100,9 @@
 
     SELECT o
     FROM orders o
-    WHERE LEN(o.items) > 0 AND
-          (EVERY i IN o.items SATISFIES i.qty > 100 AND i.price < 5.00);
+    WHERE SOME AND EVERY i IN o.items SATISFIES i.qty > 100 AND i.price < 5.00;
 
-Take note of the `LEN(o.items) > 0` conjunct.
+Take note of the `SOME AND EVERY` quantifier instead of the `EVERY` quantifier.
 Array indexes cannot be used for queries with potentially empty arrays.