private int applyProjectionAndAddToResultSet(ExecutionContext context, SelectResults resultSet,
      boolean ignoreOrderBy) throws FunctionDomainException, TypeMismatchException,
      NameResolutionException, QueryInvocationTargetException {
    List currrentRuntimeIters = context.getCurrentIterators();

    int occurrence = 0;
    ObjectType elementType = resultSet.getCollectionType().getElementType();
    boolean isStruct = elementType != null && elementType.isStructType();

    // TODO: Optimize this condition in some clean way
    boolean isLinkedStructure =
        resultSet instanceof Ordered && ((Ordered) resultSet).dataPreordered();

    ArrayList evaluatedOrderByClause = null;
    OrderByComparator comparator = null;
    boolean applyOrderBy = false;
    if (orderByAttrs != null && !ignoreOrderBy) {
      // In case PR order-by will get applied on the coordinator node
      // on the cumulative results. Apply the order-by on PR only if
      // limit is specified.
      Integer limitValue = evaluateLimitValue(context, limit);
      if (context.getPartitionedRegion() != null && limitValue < 0) {
        applyOrderBy = false;
      }
      applyOrderBy = true;
    }

    if (orderByAttrs != null && !ignoreOrderBy) {
      comparator = (OrderByComparator) ((Ordered) resultSet).comparator();
    }
    if (projAttrs == null) {
      int len = currrentRuntimeIters.size();
      Object[] values = new Object[len];
      for (int i = 0; i < len; i++) {
        RuntimeIterator iter = (RuntimeIterator) currrentRuntimeIters.get(i);
        values[i] = iter.evaluate(context);
        // For local queries with distinct, deserialize all PdxInstances
        // as we do not have a way to compare Pdx and non Pdx objects in case
        // the cache has a mix of pdx and non pdx objects.
        // We still have to honor the cache level readserialized flag in
        // case of all Pdx objects in cache
        if (distinct && !((DefaultQuery) context.getQuery()).isRemoteQuery()
            && !context.getCache().getPdxReadSerialized() && (values[i] instanceof PdxInstance)) {
          values[i] = ((PdxInstance) values[i]).getObject();
        }
      }

      // Shobhit: Add count value to the counter for this select expression.
      // Don't care about Order By for count(*).
      if (isCount() && !distinct) {
        // Counter is local to CompileSelect and not available in ResultSet
        // until
        // the end of evaluate call to this CompiledSelect object.
        countStartQueryResult++;
        occurrence = 1;
      } else {
        // if order by is present
        if (applyOrderBy) {
          StructImpl structImpl;
          if (distinct) {
            if (isStruct) {
              if (values.length == 1 && values[0] instanceof StructImpl) {
                structImpl = (StructImpl) values[0];
                comparator.addEvaluatedSortCriteria(structImpl.getFieldValues(), context);
                occurrence = resultSet.add(structImpl) ? 1 : 0;
              } else {
                comparator.addEvaluatedSortCriteria(values, context);
                occurrence = ((StructFields) resultSet).addFieldValues(values) ? 1 : 0;
              }
              // TODO:Instead of a normal Map containing which holds
              // StructImpl object
              // use a THashObject with Object[] array hashing stragtegy as we
              // are unnnecessarily
              // creating objects of type Object[]
            } else {
              comparator.addEvaluatedSortCriteria(values[0], context);
              occurrence = resultSet.add(values[0]) ? 1 : 0;
            }
          } else {
            if (isStruct) {
              if (values.length == 1 && values[0] instanceof StructImpl) {
                structImpl = (StructImpl) values[0];
                comparator.addEvaluatedSortCriteria(structImpl.getFieldValues(), context);
                occurrence = ((Bag) resultSet).addAndGetOccurence(structImpl.getFieldValues());
              } else {
                comparator.addEvaluatedSortCriteria(values, context);
                occurrence = ((Bag) resultSet).addAndGetOccurence(values);

              }
            } else {
              comparator.addEvaluatedSortCriteria(values[0], context);
              occurrence = ((Bag) resultSet).addAndGetOccurence(values[0]);
            }
          }
        } else {
          if (isLinkedStructure) {
            if (isStruct) {
              StructImpl structImpl;
              if (values.length == 1 && values[0] instanceof StructImpl) {
                structImpl = (StructImpl) values[0];
              } else {
                structImpl = new StructImpl((StructTypeImpl) elementType, values);
              }
              if (distinct) {
                occurrence = resultSet.add(structImpl) ? 1 : 0;
              } else {
                occurrence = ((Bag) resultSet).addAndGetOccurence(structImpl);
              }
            } else {
              if (distinct) {
                occurrence = resultSet.add(values[0]) ? 1 : 0;
              } else {
                occurrence = ((Bag) resultSet).addAndGetOccurence(values[0]);
              }

            }
          } else {
            if (distinct) {
              if (isStruct) {
                occurrence = ((StructFields) resultSet).addFieldValues(values) ? 1 : 0;
              } else {
                occurrence = resultSet.add(values[0]) ? 1 : 0;
              }
            } else {
              if (isStruct) {
                occurrence = ((Bag) resultSet).addAndGetOccurence(values);
              } else {
                boolean add = true;
                if (context.isCqQueryContext()) {
                  if (values[0] instanceof Region.Entry) {
                    Region.Entry e = (Region.Entry) values[0];
                    if (!e.isDestroyed()) {
                      try {
                        values[0] = new CqEntry(e.getKey(), e.getValue());
                      } catch (EntryDestroyedException ignore) {
                        // Even though isDestory() check is made, the entry could throw
                        // EntryDestroyedException if the value becomes null.
                        add = false;
                      }
                    } else {
                      add = false;
                    }
                  }
                }
                if (add) {
                  occurrence = ((Bag) resultSet).addAndGetOccurence(values[0]);
                }
              }
            }
          }
        }
      }
    } else { // One or more projection attributes
      int projCount = projAttrs.size();
      Object[] values = new Object[projCount];
      for (int i = 0; i < projCount; i++) {
        Object[] projDef = (Object[]) projAttrs.get(i);
        values[i] = ((CompiledValue) projDef[1]).evaluate(context);
        // For local queries with distinct, deserialize all PdxInstances
        // as we do not have a way to compare Pdx and non Pdx objects in case
        // the cache has a mix of pdx and non pdx objects.
        // We still have to honor the cache level readserialized flag in
        // case of all Pdx objects in cache.
        // Also always convert PdxString to String before adding to resultset
        // for remote queries
        if (!((DefaultQuery) context.getQuery()).isRemoteQuery()) {
          if (distinct && values[i] instanceof PdxInstance
              && !context.getCache().getPdxReadSerialized()) {
            values[i] = ((PdxInstance) values[i]).getObject();
          } else if (values[i] instanceof PdxString) {
            values[i] = values[i].toString();
          }
        } else if (values[i] instanceof PdxString) {
          values[i] = values[i].toString();
        }
      }
      // if order by is present
      if (applyOrderBy) {
        if (distinct) {
          if (isStruct) {
            comparator.addEvaluatedSortCriteria(values, context);
            // Occurrence field is used to identify the corrcet number of
            // iterations
            // required to implement the limit based on the presence or absence
            // of distinct clause
            occurrence = ((StructFields) resultSet).addFieldValues(values) ? 1 : 0;
          } else {
            comparator.addEvaluatedSortCriteria(values[0], context);
            occurrence = resultSet.add(values[0]) ? 1 : 0;
          }
        } else {
          if (isStruct) {
            comparator.addEvaluatedSortCriteria(values, context);
            occurrence = ((Bag) resultSet).addAndGetOccurence(values);
          } else {
            comparator.addEvaluatedSortCriteria(values[0], context);
            occurrence = ((Bag) resultSet).addAndGetOccurence(values[0]);
          }
        }
      } else {
        if (isLinkedStructure) {
          if (isStruct) {
            StructImpl structImpl = new StructImpl((StructTypeImpl) elementType, values);
            if (distinct) {
              occurrence = resultSet.add(structImpl) ? 1 : 0;
            } else {
              occurrence = ((Bag) resultSet).addAndGetOccurence(structImpl);
            }

          } else {
            if (distinct) {
              occurrence = resultSet.add(values[0]) ? 1 : 0;
            } else {
              occurrence = ((Bag) resultSet).addAndGetOccurence(values[0]);
            }
          }
        } else {
          if (distinct) {
            if (isStruct) {
              occurrence = ((StructFields) resultSet).addFieldValues(values) ? 1 : 0;
            } else {
              occurrence = resultSet.add(values[0]) ? 1 : 0;
            }
          } else {
            if (isStruct) {
              occurrence = ((Bag) resultSet).addAndGetOccurence(values);
            } else {
              occurrence = ((Bag) resultSet).addAndGetOccurence(values[0]);
            }
          }
        }
      }
    }
    return occurrence;
  }
This function should be used to create a StructType for those queries which have * as
projection attribute (implying null projection attribute) & multiple from clauses
geode-core/src/main/java/org/apache/geode/cache/query/internal/CompiledSelect.java