private Object doExecuteQuery(final DefaultQuery query,
      final ExecutionContext executionContext,
      final Object[] parameters,
      final Set buckets)
      throws FunctionDomainException, TypeMismatchException, NameResolutionException,
      QueryInvocationTargetException, ForceReattemptException {
    if (logger.isDebugEnabled()) {
      logger.debug("Executing query :{}", query);
    }

    HashSet<Integer> allBuckets = new HashSet<>();

    if (buckets == null) { // remote buckets
      final Iterator remoteIter = getRegionAdvisor().getBucketSet().iterator();
      try {
        while (remoteIter.hasNext()) {
          allBuckets.add((Integer) remoteIter.next());
        }
      } catch (NoSuchElementException ignore) {
      }
    } else { // local buckets
      Iterator localIter = null;
      if (dataStore != null) {
        localIter = buckets.iterator();
      } else {
        localIter = Collections.emptyIterator();
      }
      try {
        while (localIter.hasNext()) {
          allBuckets.add((Integer) localIter.next());
        }
      } catch (NoSuchElementException ignore) {
      }
    }

    if (allBuckets.size() == 0) {
      if (logger.isDebugEnabled()) {
        logger.debug("No bucket storage allocated. PR has no data yet.");
      }
      ResultsSet resSet = new ResultsSet();
      resSet.setElementType(new ObjectTypeImpl(
          getValueConstraint() == null ? Object.class : getValueConstraint()));
      return resSet;
    }

    CompiledSelect selectExpr = query.getSimpleSelect();
    if (selectExpr == null) {
      throw new IllegalArgumentException(
          "query must be a select expression only");
    }

    // this can return a BAG even if it's a DISTINCT select expression,
    // since the expectation is that the duplicates will be removed at the end
    SelectResults results = selectExpr.getEmptyResultSet(parameters, getCache(), query);

    PartitionedRegionQueryEvaluator prqe = new PartitionedRegionQueryEvaluator(getSystem(),
        this, query, executionContext, parameters, results, allBuckets);
    for (;;) {
      getCancelCriterion().checkCancelInProgress(null);
      boolean interrupted = Thread.interrupted();
      try {
        results = prqe.queryBuckets(null);
        break;
      } catch (InterruptedException ignore) {
        interrupted = true;
      } catch (FunctionDomainException e) {
        throw e;
      } catch (TypeMismatchException e) {
        throw e;
      } catch (NameResolutionException e) {
        throw e;
      } catch (QueryInvocationTargetException e) {
        throw e;
      } catch (QueryException qe) {
        throw new QueryInvocationTargetException(
            String.format("Unexpected query exception occurred during query execution %s",
                qe.getMessage()),
            qe);
      } finally {
        if (interrupted) {
          Thread.currentThread().interrupt();
        }
      }
    } // for

    // Drop Duplicates if this is a DISTINCT query
    boolean allowsDuplicates = results.getCollectionType().allowsDuplicates();
    // No need to apply the limit to the SelectResults.
    // We know that even if we do not apply the limit,
    // the results will satisfy the limit
    // as it has been evaluated in the iteration of List to
    // populate the SelectsResuts
    // So if the results is instance of ResultsBag or is a StructSet or
    // a ResultsSet, if the limit exists, the data set size will
    // be exactly matching the limit
    if (selectExpr.isDistinct()) {
      // don't just convert to a ResultsSet (or StructSet), since
      // the bags can convert themselves to a Set more efficiently
      ObjectType elementType = results.getCollectionType().getElementType();
      if (selectExpr.getOrderByAttrs() != null) {
        // Set limit also, its not applied while building the final result set as order by is
        // involved.
      } else if (allowsDuplicates) {
        results = new ResultsCollectionWrapper(elementType, results.asSet());
      }
      if (selectExpr.isCount() && (results.isEmpty() || selectExpr.isDistinct())) {
        // Constructor with elementType not visible.
        SelectResults resultCount = new ResultsBag(getCachePerfStats());
        resultCount.setElementType(new ObjectTypeImpl(Integer.class));
        ((Bag) resultCount).addAndGetOccurence(results.size());
        return resultCount;
      }
    }
    return results;
  }
If ForceReattemptException is thrown then the caller must loop and call us again.

@throws ForceReattemptException if one of the buckets moved out from under us
geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java