private void sendResultsAsObjectArray(SelectResults<?> selectResults, int numberOfChunks,
      ServerConnection servConn, boolean isStructs,
      CollectionType collectionType,
      String queryString, ServerCQ cqQuery,
      boolean sendResults)
      throws IOException {
    int resultIndex = 0;
    // For CQ only as we dont want CQEntries which have null values.
    int cqResultIndex = 0;
    Object[] objs = selectResults.toArray();
    for (int j = 0; j < numberOfChunks; j++) {
      boolean incompleteArray = false;
      if (logger.isTraceEnabled()) {
        logger.trace("{}: Creating chunk: {}", servConn.getName(), j);
      }
      Object[] results = new Object[MAXIMUM_CHUNK_SIZE];
      for (int i = 0; i < MAXIMUM_CHUNK_SIZE; i++) {
        if ((resultIndex) == objs.length) {
          incompleteArray = true;
          break;
        }
        if (logger.isTraceEnabled()) {
          logger.trace("{}: Adding entry [{}] to query results: {}", servConn.getName(),
              resultIndex, objs[resultIndex]);
        }
        if (cqQuery != null) {
          CqEntry e = (CqEntry) objs[resultIndex];
          // The value may have become null because of entry invalidation.
          if (e.getValue() == null) {
            resultIndex++;
            // i will get incremented anyway so we need to decrement it back so
            // that results[i] is not null.
            i--;
            continue;
          }
          // Add the key into CQ results cache.
          // For PR the Result caching is not yet supported.
          // cqQuery.cqResultsCacheInitialized is added to take care
          // of CQ execute requests that are re-sent. In that case no
          // need to update the Results cache.
          if (!cqQuery.isPR()) {
            cqQuery.addToCqResultKeys(e.getKey());
          }

          // Add to the Results object array.
          results[i] = e.getKeyValuePair();
        } else {
          // instance check added to fix bug 40516.
          if (isStructs && (objs[resultIndex] instanceof Struct)) {
            results[i] = ((Struct) objs[resultIndex]).getFieldValues();
          } else {
            results[i] = objs[resultIndex];
          }
        }
        resultIndex++;
        cqResultIndex++;
      }
      // Shrink array if necessary. This will occur if the number
      // of entries in the chunk does not divide evenly into the
      // number of entries in the result set.
      if (incompleteArray) {
        final Object[] newResults;
        if (cqQuery == null) {
          newResults = new Object[resultIndex % MAXIMUM_CHUNK_SIZE];
        } else {
          newResults = new Object[cqResultIndex % MAXIMUM_CHUNK_SIZE];
        }
        System.arraycopy(results, 0, newResults, 0, newResults.length);
        results = newResults;
      }

      if (sendResults) {
        writeQueryResponseChunk(results, collectionType, (resultIndex == objs.length),
            servConn);

        if (logger.isDebugEnabled()) {
          logger.debug("{}: Sent chunk ({} of {}) of query response for query: {}",
              servConn.getName(), (j + 1), numberOfChunks, queryString);
        }
      }
      // If we have reached the last element of SelectResults then we should
      // break out of loop here only.
      if (resultIndex == objs.length) {
        break;
      }
    }
  }
Process the give query and sends the resulset back to the client.

@return true if successful execution false in case of failure.
geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/BaseCommandQuery.java