private SelectResults singleBaseCollectionFilterEvaluate(ExecutionContext context,
      SelectResults intermediateResults, final boolean completeExpansionNeeded,
      @Retained CompiledValue iterOperands, IndexInfo indexInfo, RuntimeIterator[] indpndntItr,
      boolean isIntersection, boolean conditioningNeeded, boolean evaluateProj)
      throws TypeMismatchException, FunctionDomainException,
      NameResolutionException, QueryInvocationTargetException {
    ObjectType resultType = indexInfo._index.getResultSetType();
    int indexFieldsSize = -1;
    SelectResults set = null;
    boolean createEmptySet = false;
    // Direct comparison with UNDEFINED will always return empty set
    Object key = indexInfo.evaluateIndexKey(context);
    createEmptySet = (key != null && key.equals(QueryService.UNDEFINED));
    if (resultType instanceof StructType) {
      indexFieldsSize = ((StructTypeImpl) resultType).getFieldNames().length;
    } else {
      indexFieldsSize = 1;
    }

    // if the key is the LEFT operand, then reflect the operator
    // before the index lookup
    int op = reflectOnOperator(indexInfo._key());
    // actual index lookup
    QueryObserver observer = QueryObserverHolder.getInstance();
    List projAttrib = null;
    /*
     * Asif : First obtain the match level of index resultset. If the match level happens to be zero
     * , this implies that we just have to change the StructType ( again if only the Index resultset
     * is a StructBag). If the match level is zero & expand to to top level flag is true & iff the
     * total no. of iterators in current scope is greater than the no. of fields in StructBag , then
     * only we need to do any expansion.
     *
     */

    try {
      if (!createEmptySet) {
        observer.beforeIndexLookup(indexInfo._index, op, key);
        context.cachePut(CompiledValue.INDEX_INFO, indexInfo);
      }
      // //////////////////////////////////////////////////////////
      // Asif:Create an instance of IndexConditionHelper to see , if the match
      // level is zero & expansion is to Group level & that no reshuffling is
      // needed.
      // If this holds true , then we will try to evaluate iter operand while
      // collecting the results itself. Pass the iter operand as null so that
      // we get the right idea. Also right now we will assume that only single
      // iterator cases will be candidates for this oprtmization.
      // dependent iterators will come later.
      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();
      }
      // ////////////////////////////////////////////////////////////////
      if (!conditioningNeeded) {
        ObjectType projResultType =
            evaluateProj ? (ObjectType) context.cacheGet(RESULT_TYPE) : null;
        if (projResultType != null) {
          resultType = projResultType;
          projAttrib = (List) context.cacheGet(PROJ_ATTRIB);
          context.cachePut(RESULT_TYPE, Boolean.TRUE);
        }

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

          if (intermediateResults != null && context.getQuery() != null
              && ((DefaultQuery) context.getQuery()).getSelect().isDistinct()) {
            set = intermediateResults;
            intermediateResults = null;
          } else {
            if (resultType instanceof StructType) {
              context.getCache().getLogger()
                  .fine("StructType resultType.class=" + resultType.getClass().getName());
              if (useLinkedDataStructure) {
                set = context.isDistinct() ? new LinkedStructSet((StructTypeImpl) resultType)
                    : new SortedResultsBag<>(resultType, nullValuesAtStart);
              } else {
                set = QueryUtils.createStructCollection(context, (StructTypeImpl) resultType);
              }
              indexFieldsSize = ((StructTypeImpl) resultType).getFieldNames().length;
            } else {
              context.getCache().getLogger()
                  .fine("non-StructType resultType.class=" + resultType.getClass().getName());
              if (useLinkedDataStructure) {
                set = context.isDistinct() ? new LinkedResultSet(resultType)
                    : new SortedResultsBag(resultType, nullValuesAtStart);
              } else {
                set = QueryUtils.createResultCollection(context, resultType);
              }
              indexFieldsSize = 1;
            }
          }
        }
        if (!createEmptySet) {
          indexInfo._index.query(key, op, set, iterOperands,
              indpndntItr != null ? indpndntItr[0] : null, context, projAttrib, intermediateResults,
              isIntersection);
        }
      } else {
        if (resultType instanceof StructType) {
          context.getCache().getLogger()
              .fine("StructType resultType.class=" + resultType.getClass().getName());
          if (useLinkedDataStructure) {
            set = context.isDistinct() ? new LinkedStructSet((StructTypeImpl) resultType)
                : new SortedResultsBag<>(resultType, nullValuesAtStart);
          } else {
            set = QueryUtils.createStructCollection(context, (StructTypeImpl) resultType);
          }

          indexFieldsSize = ((StructTypeImpl) resultType).getFieldNames().length;
        } else {
          context.getCache().getLogger()
              .fine("non-StructType resultType.class=" + resultType.getClass().getName());
          if (useLinkedDataStructure) {
            set = context.isDistinct() ? new LinkedResultSet(resultType)
                : new SortedResultsBag(resultType, nullValuesAtStart);
          } else {
            set = QueryUtils.createResultCollection(context, resultType);
          }
          indexFieldsSize = 1;
        }
        if (!createEmptySet) {
          indexInfo._index.query(key, op, set, context); // tow rows qualify from index
        }
        // look up. rahul
      }
    } finally {
      if (!createEmptySet) {
        observer.afterIndexLookup(set);
      }
    }
    if (conditioningNeeded) {
      return QueryUtils.getConditionedIndexResults(set, indexInfo, context, indexFieldsSize,
          completeExpansionNeeded, iterOperands, indpndntItr);
    } else {
      return set;
    }
  }
evaluate as a filter, producing an intermediate result set. This may require iteration if there
is no index available. Asif :The booelan true implies that CompiledComparsion when existing on
its own always requires a Completeexpansion to top level iterators. This flag can get toggled
to false only from inside a GroupJunction

@param intermediateResults if this parameter is provided, and we have to iterate, then iterate
       over this result set instead of the entire base collection.
geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledComparison.java