/**
   * INTERNAL: Execute the query. Get the rows and build the object from the rows.
   *
   * @exception DatabaseException - an error has occurred on the database
   * @return java.lang.Object collection of objects resulting from execution of query.
   */
  protected Object executeObjectLevelReadQuery() throws DatabaseException {
    Object result = null;

    if (getContainerPolicy().overridesRead()) {
      return getContainerPolicy().execute();
    }

    if (this.descriptor.isDescriptorForInterface()) {
      Object returnValue =
          this.descriptor.getInterfacePolicy().selectAllObjectsUsingMultipleTableSubclassRead(this);
      setExecutionTime(System.currentTimeMillis());
      return returnValue;
    }

    List rows = getQueryMechanism().selectAllRows();
    setExecutionTime(System.currentTimeMillis());

    // If using 1-m joins, must set all rows.
    if (hasJoining() && this.joinedAttributeManager.isToManyJoin()) {
      this.joinedAttributeManager.setDataResults(rows, this.session);
    }

    if (this.session.isUnitOfWork()) {
      result =
          registerResultInUnitOfWork(
              rows, (UnitOfWorkImpl) this.session, this.translationRow, true); //
    } else {
      result = getContainerPolicy().containerInstance(rows.size());
      this.descriptor.getObjectBuilder().buildObjectsInto(this, rows, result);
    }

    if (this.shouldIncludeData) {
      ComplexQueryResult complexResult = new ComplexQueryResult();
      complexResult.setResult(result);
      complexResult.setData(rows);
      return complexResult;
    }

    // Add the other (already registered) results and return them.
    if (getDescriptor().hasTablePerClassPolicy()) {
      result =
          containerPolicy.concatenateContainers(
              result,
              getDescriptor()
                  .getTablePerClassPolicy()
                  .selectAllObjectsUsingMultipleTableSubclassRead(this));
    }

    return result;
  }
  /**
   * INTERNAL: All objects queried via a UnitOfWork get registered here. If the query went to the
   * database.
   *
   * <p>Involves registering the query result individually and in totality, and hence refreshing /
   * conforming is done here.
   *
   * @param result may be collection (read all) or an object (read one), or even a cursor. If in
   *     transaction the shared cache will be bypassed, meaning the result may not be originals from
   *     the parent but raw database rows.
   * @param unitOfWork the unitOfWork the result is being registered in.
   * @param arguments the original arguments/parameters passed to the query execution. Used by
   *     conforming
   * @param buildDirectlyFromRows If in transaction must construct a registered result from raw
   *     database rows.
   * @return the final (conformed, refreshed, wrapped) UnitOfWork query result
   */
  public Object registerResultInUnitOfWork(
      Object result,
      UnitOfWorkImpl unitOfWork,
      AbstractRecord arguments,
      boolean buildDirectlyFromRows) {
    // For bug 2612366: Conforming results in UOW extremely slow.
    // Replacing results with registered versions in the UOW is a part of
    // conforming and is now done while conforming to maximize performance.
    if (shouldConformResultsInUnitOfWork()
        || this.descriptor.shouldAlwaysConformResultsInUnitOfWork()) {
      return conformResult(result, unitOfWork, arguments, buildDirectlyFromRows);
    }

    // When building directly from rows, one of the performance benefits
    // is that we no longer have to wrap and then unwrap the originals.
    // result is just a vector, not a collection of wrapped originals.
    // Also for cursors the initial connection is automatically registered.
    if (buildDirectlyFromRows) {
      List<AbstractRecord> rows = (List<AbstractRecord>) result;
      ContainerPolicy cp = getContainerPolicy();
      int size = rows.size();
      Object clones = cp.containerInstance(size);
      for (int index = 0; index < size; index++) {
        AbstractRecord row = rows.get(index);

        // null is placed in the row collection for 1-m joining to filter duplicate rows.
        if (row != null) {
          Object clone = buildObject(row);
          cp.addInto(clone, clones, unitOfWork, row, this);
        }
      }
      return clones;
    }

    ContainerPolicy cp;
    Cursor cursor = null;

    // If the query is redirected then the collection returned might no longer
    // correspond to the original container policy.  CR#2342-S.M.
    if (getRedirector() != null) {
      cp = ContainerPolicy.buildPolicyFor(result.getClass());
    } else {
      cp = getContainerPolicy();
    }

    // In the case of cursors just register the initially read collection.
    if (cp.isCursorPolicy()) {
      cursor = (Cursor) result;
      // In nested UnitOfWork session might have been session of the parent.
      cursor.setSession(unitOfWork);
      cp = ContainerPolicy.buildPolicyFor(ClassConstants.Vector_class);
      result = cursor.getObjectCollection();
    }

    Object clones = cp.containerInstance(cp.sizeFor(result));
    AbstractSession sessionToUse = unitOfWork.getParent();
    for (Object iter = cp.iteratorFor(result); cp.hasNext(iter); ) {
      Object object = cp.next(iter, sessionToUse);
      Object clone = registerIndividualResult(object, unitOfWork, this.joinedAttributeManager);
      cp.addInto(clone, clones, unitOfWork);
    }
    if (cursor != null) {
      cursor.setObjectCollection((Vector) clones);
      return cursor;
    } else {
      return clones;
    }
  }