SelectResults singleBaseCollectionFilterEvaluate(ExecutionContext context,
      SelectResults intermediateResults, boolean completeExpansionNeeded,
      CompiledValue iterOperands, IndexInfo indexInfo, RuntimeIterator[] indpndntItr,
      boolean isIntersection, boolean conditioningNeeded, boolean evalProj)
      throws TypeMismatchException, FunctionDomainException,
      NameResolutionException, QueryInvocationTargetException {
    ObjectType resultType = indexInfo._index.getResultSetType();
    int indexFieldsSize = -1;
    SelectResults results = null;
    if (resultType instanceof StructType) {
      indexFieldsSize = ((StructTypeImpl) resultType).getFieldNames().length;
    } else {
      indexFieldsSize = 1;
    }
    boolean useLinkedDataStructure = false;
    boolean nullValuesAtStart = true;
    Boolean orderByClause = (Boolean) context.cacheGet(CompiledValue.CAN_APPLY_ORDER_BY_AT_INDEX);
    if (orderByClause != null && orderByClause) {
      List orderByAttrs = (List) context.cacheGet(CompiledValue.ORDERBY_ATTRIB);
      useLinkedDataStructure = orderByAttrs.size() == 1;
      nullValuesAtStart = !((CompiledSortCriterion) orderByAttrs.get(0)).getCriterion();
    }

    List projAttrib = null;

    ObjectType projResultType = null;
    if (!conditioningNeeded) {
      projResultType = evalProj ? (ObjectType) context.cacheGet(RESULT_TYPE) : null;
      if (projResultType != null) {
        resultType = projResultType;
        context.cachePut(RESULT_TYPE, Boolean.TRUE);
        projAttrib = (List) context.cacheGet(PROJ_ATTRIB);
      }
      if (isIntersection) {
        if (resultType instanceof StructType) {
          context.getCache().getLogger()
              .fine("StructType resultType.class=" + resultType.getClass().getName());
          if (useLinkedDataStructure) {
            results = context.isDistinct() ? new LinkedStructSet((StructTypeImpl) resultType)
                : new SortedResultsBag<>(resultType, nullValuesAtStart);
          } else {
            results = QueryUtils.createStructCollection(context, (StructTypeImpl) resultType);
          }
          indexFieldsSize = ((StructTypeImpl) resultType).getFieldNames().length;
        } else {
          context.getCache().getLogger()
              .fine("non-StructType resultType.class=" + resultType.getClass().getName());
          if (useLinkedDataStructure) {
            results = context.isDistinct() ? new LinkedResultSet(resultType)
                : new SortedResultsBag(resultType, nullValuesAtStart);
          } else {
            results = QueryUtils.createResultCollection(context, resultType);
          }
          indexFieldsSize = 1;
        }
      } else {
        if (intermediateResults != null && !completeExpansionNeeded) {
          results = intermediateResults;
        } else {
          if (resultType instanceof StructType) {
            context.getCache().getLogger()
                .fine("StructType resultType.class=" + resultType.getClass().getName());
            if (useLinkedDataStructure) {
              results = context.isDistinct() ? new LinkedStructSet((StructTypeImpl) resultType)
                  : new SortedResultsBag<>(resultType, nullValuesAtStart);
            } else {
              results = QueryUtils.createStructCollection(context, (StructTypeImpl) resultType);
            }
            indexFieldsSize = ((StructTypeImpl) resultType).getFieldNames().length;
          } else {
            context.getCache().getLogger()
                .fine("non-StructType resultType.class=" + resultType.getClass().getName());
            if (useLinkedDataStructure) {
              results = context.isDistinct() ? new LinkedResultSet(resultType)
                  : new SortedResultsBag(resultType, nullValuesAtStart);
            } else {
              results = QueryUtils.createResultCollection(context, resultType);
            }
            indexFieldsSize = 1;
          }
        }
      }

    } else {
      if (resultType instanceof StructType) {
        context.getCache().getLogger()
            .fine("StructType resultType.class=" + resultType.getClass().getName());
        if (useLinkedDataStructure) {
          results = context.isDistinct() ? new LinkedStructSet((StructTypeImpl) resultType)
              : new SortedResultsBag<>(resultType, nullValuesAtStart);
        } else {
          results = QueryUtils.createStructCollection(context, (StructTypeImpl) resultType);
        }
        indexFieldsSize = ((StructTypeImpl) resultType).getFieldNames().length;
      } else {
        context.getCache().getLogger()
            .fine("non-StructType resultType.class=" + resultType.getClass().getName());
        if (useLinkedDataStructure) {
          results = context.isDistinct() ? new LinkedResultSet(resultType)
              : new SortedResultsBag(resultType, nullValuesAtStart);
        } else {
          results = QueryUtils.createResultCollection(context, resultType);
        }
        indexFieldsSize = 1;
      }
    }

    QueryObserver observer = QueryObserverHolder.getInstance();
    try {
      Object evalColln = evaluateColln(context);
      observer.beforeIndexLookup(indexInfo._index, TOK_EQ, evalColln);
      // We need to reset the result type just in case the colln turned out to
      // be a compiled comparison which could change the result type
      // Exec caches are incorrectly shared across all queries, this would result
      // in overriding the result type. Once the result type was overridden
      // multiple projections and class cast exceptions could result due to
      // unexpected values overwriting expected values
      if (!conditioningNeeded) {
        if (projResultType != null) {
          resultType = projResultType;
          context.cachePut(RESULT_TYPE, Boolean.TRUE);
        }
      }
      // handle each type of collection that we support
      if (evalColln instanceof Map) {
        for (final Object o : ((Map) evalColln).entrySet()) {
          queryIndex(o, indexInfo, results, iterOperands, indpndntItr, context,
              projAttrib, conditioningNeeded);
        }

      } else if (evalColln instanceof Collection) {
        Object key = indexInfo.evaluateIndexKey(context);
        // If the index is a map index, the key is actually an object[] tuple that contains the map
        // key in the [1]
        // and the evalColln in the [0] position
        if (key instanceof Object[]) {
          for (final Object o : (Iterable) ((Object[]) key)[0]) {
            queryIndex(new Object[] {o, ((Object[]) key)[1]}, indexInfo, results,
                iterOperands, indpndntItr, context, projAttrib, conditioningNeeded);
          }
        } else {
          // Removing duplicates from the collection
          HashSet set = new HashSet((Collection) evalColln);
          for (final Object o : set) {
            queryIndex(o, indexInfo, results, iterOperands, indpndntItr, context,
                projAttrib, conditioningNeeded);
          }
        }
      } else {

        if (!evalColln.getClass().isArray()) {
          throw new TypeMismatchException("Operand of IN cannot be interpreted as a Collection. "
              + "Is instance of " + evalColln.getClass().getName());
        }

        int evalCollnLength = Array.getLength(evalColln);
        for (int i = 0; i < evalCollnLength; ++i) {
          queryIndex(Array.get(evalColln, i), indexInfo, results, iterOperands, indpndntItr,
              context, projAttrib, conditioningNeeded);
        }
      }

      if (conditioningNeeded) {
        results = QueryUtils.getConditionedIndexResults(results, indexInfo, context,
            indexFieldsSize, completeExpansionNeeded, iterOperands, indpndntItr);
      } else {
        if (isIntersection && intermediateResults != null) {
          results = QueryUtils.intersection(intermediateResults, results, context);
        }
      }
      return results;
    } finally {
      observer.afterIndexLookup(results);
    }
  }
evaluate as a filter, involving a single iterator. Use an index if possible.

Invariant: the receiver is dependent on the current iterator.
geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledIn.java