private FromElement createCollectionJoin(JoinSequence collectionJoinSequence, String tableAlias)
     throws SemanticException {
   String text = queryableCollection.getTableName();
   AST ast = createFromElement(text);
   FromElement destination = (FromElement) ast;
   Type elementType = queryableCollection.getElementType();
   if (elementType.isCollectionType()) {
     throw new SemanticException("Collections of collections are not supported!");
   }
   destination.initializeCollection(fromClause, classAlias, tableAlias);
   destination.setType(JOIN_FRAGMENT); // Tag this node as a JOIN.
   destination.setIncludeSubclasses(false); // Don't include subclasses in the join.
   destination.setCollectionJoin(true); // This is a clollection join.
   destination.setJoinSequence(collectionJoinSequence);
   destination.setOrigin(origin, false);
   destination.setCollectionTableAlias(tableAlias);
   //		origin.addDestination( destination );
   // This was the cause of HHH-242
   //		origin.setType( FROM_FRAGMENT );			// Set the parent node type so that the AST is properly
   // formed.
   origin.setText(""); // The destination node will have all the FROM text.
   origin.setCollectionJoin(
       true); // The parent node is a collection join too (voodoo - see JoinProcessor)
   fromClause.addCollectionJoinFromElementByPath(path, destination);
   fromClause.getWalker().addQuerySpaces(queryableCollection.getCollectionSpaces());
   return destination;
 }
 public void resolveCollectionProperty(AST expr) throws SemanticException {
   String propertyName = CollectionProperties.getNormalizedPropertyName(getMethodName());
   if (expr instanceof FromReferenceNode) {
     FromReferenceNode collectionNode = (FromReferenceNode) expr;
     // If this is 'elements' then create a new FROM element.
     if (CollectionPropertyNames.COLLECTION_ELEMENTS.equals(propertyName)) {
       handleElements(collectionNode, propertyName);
     } else {
       // Not elements(x)
       fromElement = collectionNode.getFromElement();
       setDataType(fromElement.getPropertyType(propertyName, propertyName));
       selectColumns = fromElement.toColumns(fromElement.getTableAlias(), propertyName, inSelect);
     }
     if (collectionNode instanceof DotNode) {
       prepareAnyImplicitJoins((DotNode) collectionNode);
     }
     if (!inSelect) {
       fromElement.setText("");
       fromElement.setUseWhereFragment(false);
     }
     prepareSelectColumns(selectColumns);
     setText(selectColumns[0]);
     setType(SqlTokenTypes.SQL_TOKEN);
   } else {
     throw new SemanticException(
         "Unexpected expression " + expr + " found for collection function " + propertyName);
   }
 }
 private FromElement createManyToMany(
     String role,
     String associatedEntityName,
     String roleAlias,
     Queryable entityPersister,
     EntityType type,
     int joinType)
     throws SemanticException {
   FromElement elem;
   SessionFactoryHelper sfh = fromClause.getSessionFactoryHelper();
   if (inElementsFunction /*implied*/) {
     // For implied many-to-many, just add the end join.
     JoinSequence joinSequence = createJoinSequence(roleAlias, joinType);
     elem = createJoin(associatedEntityName, roleAlias, joinSequence, type, true);
   } else {
     // For an explicit many-to-many relationship, add a second join from the intermediate
     // (many-to-many) table to the destination table.  Also, make sure that the from element's
     // idea of the destination is the destination table.
     String tableAlias =
         fromClause.getAliasGenerator().createName(entityPersister.getEntityName());
     String[] secondJoinColumns = sfh.getCollectionElementColumns(role, roleAlias);
     // Add the second join, the one that ends in the destination table.
     JoinSequence joinSequence = createJoinSequence(roleAlias, joinType);
     joinSequence.addJoin(
         sfh.getElementAssociationType(collectionType), tableAlias, joinType, secondJoinColumns);
     elem = createJoin(associatedEntityName, tableAlias, joinSequence, type, false);
     elem.setUseFromFragment(true);
   }
   return elem;
 }
Example #4
0
 private boolean isReturnableEntity(SelectExpression selectExpression) throws SemanticException {
   FromElement fromElement = selectExpression.getFromElement();
   boolean isFetchOrValueCollection =
       fromElement != null
           && (fromElement.isFetch() || fromElement.isCollectionOfValuesOrComponents());
   if (isFetchOrValueCollection) {
     return false;
   } else {
     return selectExpression.isReturnableEntity();
   }
 }
Example #5
0
  /**
   * Prepares a derived (i.e., not explicitly defined in the query) select clause.
   *
   * @param fromClause The from clause to which this select clause is linked.
   */
  public void initializeDerivedSelectClause(FromClause fromClause) throws SemanticException {
    if (prepared) {
      throw new IllegalStateException("SelectClause was already prepared!");
    }
    // Used to be tested by the TCK but the test is no longer here
    //		if ( getSessionFactoryHelper().isStrictJPAQLComplianceEnabled() && !getWalker().isSubQuery()
    // ) {
    //			// NOTE : the isSubQuery() bit is a temporary hack...
    //			throw new QuerySyntaxException( "JPA-QL compliance requires select clause" );
    //		}
    List fromElements = fromClause.getProjectionList();

    ASTAppender appender =
        new ASTAppender(getASTFactory(), this); // Get ready to start adding nodes.
    int size = fromElements.size();
    ArrayList queryReturnTypeList = new ArrayList(size);

    Iterator iterator = fromElements.iterator();
    for (int k = 0; iterator.hasNext(); k++) {
      FromElement fromElement = (FromElement) iterator.next();
      Type type = fromElement.getSelectType();

      addCollectionFromElement(fromElement);

      if (type != null) {
        boolean collectionOfElements = fromElement.isCollectionOfValuesOrComponents();
        if (!collectionOfElements) {
          if (!fromElement.isFetch()) {
            // Add the type to the list of returned sqlResultTypes.
            queryReturnTypeList.add(type);
          }
          fromElementsForLoad.add(fromElement);
          // Generate the select expression.
          String text = fromElement.renderIdentifierSelect(size, k);
          SelectExpressionImpl generatedExpr =
              (SelectExpressionImpl) appender.append(SqlTokenTypes.SELECT_EXPR, text, false);
          if (generatedExpr != null) {
            generatedExpr.setFromElement(fromElement);
          }
        }
      }
    }

    // Get all the select expressions (that we just generated) and render the select.
    SelectExpression[] selectExpressions = collectSelectExpressions();

    if (getWalker().isShallowQuery()) {
      renderScalarSelects(selectExpressions, fromClause);
    } else {
      renderNonScalarSelects(selectExpressions, fromClause);
    }
    finishInitialization(queryReturnTypeList);
  }
 private void prepareAnyImplicitJoins(DotNode dotNode) throws SemanticException {
   if (dotNode.getLhs() instanceof DotNode) {
     DotNode lhs = (DotNode) dotNode.getLhs();
     FromElement lhsOrigin = lhs.getFromElement();
     if (lhsOrigin != null && "".equals(lhsOrigin.getText())) {
       String lhsOriginText =
           lhsOrigin.getQueryable().getTableName() + " " + lhsOrigin.getTableAlias();
       lhsOrigin.setText(lhsOriginText);
     }
     prepareAnyImplicitJoins(lhs);
   }
 }
Example #7
0
 void registerFromElement(FromElement element) {
   fromElements.add(element);
   String classAlias = element.getClassAlias();
   if (classAlias != null) {
     // The HQL class alias refers to the class name.
     fromElementByClassAlias.put(classAlias, element);
   }
   // Associate the table alias with the element.
   String tableAlias = element.getTableAlias();
   if (tableAlias != null) {
     fromElementByTableAlias.put(tableAlias, element);
   }
 }
 private FromElement initializeJoin(
     String path,
     FromElement destination,
     JoinSequence joinSequence,
     String[] columns,
     FromElement origin,
     boolean manyToMany) {
   destination.setType(JOIN_FRAGMENT);
   destination.setJoinSequence(joinSequence);
   destination.setColumns(columns);
   destination.setOrigin(origin, manyToMany);
   fromClause.addJoinByPathMap(path, destination);
   return destination;
 }
  private void typeDiscriminator(AST path) throws SemanticException {
    if (path == null) {
      throw new SemanticException("type() discriminator reference has no path!");
    }

    FromReferenceNode pathAsFromReferenceNode = (FromReferenceNode) path;
    FromElement fromElement = pathAsFromReferenceNode.getFromElement();
    TypeDiscriminatorMetadata typeDiscriminatorMetadata =
        fromElement.getTypeDiscriminatorMetadata();

    setDataType(typeDiscriminatorMetadata.getResolutionType());
    setText(typeDiscriminatorMetadata.getSqlFragment());
    setType(SqlTokenTypes.SQL_TOKEN);
  }
  FromElement createCollection(
      QueryableCollection queryableCollection,
      String role,
      int joinType,
      boolean fetchFlag,
      boolean indexed)
      throws SemanticException {
    if (!collection) {
      throw new IllegalStateException("FromElementFactory not initialized for collections!");
    }
    this.inElementsFunction = indexed;
    FromElement elem;
    this.queryableCollection = queryableCollection;
    collectionType = queryableCollection.getCollectionType();
    String roleAlias = fromClause.getAliasGenerator().createName(role);

    // Correlated subqueries create 'special' implied from nodes
    // because correlated subselects can't use an ANSI-style join
    boolean explicitSubqueryFromElement = fromClause.isSubQuery() && !implied;
    if (explicitSubqueryFromElement) {
      String pathRoot = StringHelper.root(path);
      FromElement origin = fromClause.getFromElement(pathRoot);
      if (origin == null || origin.getFromClause() != fromClause) {
        implied = true;
      }
    }

    // super-duper-classic-parser-regression-testing-mojo-magic...
    if (explicitSubqueryFromElement && DotNode.useThetaStyleImplicitJoins) {
      implied = true;
    }

    Type elementType = queryableCollection.getElementType();
    if (elementType.isEntityType()) { // A collection of entities...
      elem = createEntityAssociation(role, roleAlias, joinType);
    } else if (elementType.isComponentType()) { // A collection of components...
      JoinSequence joinSequence = createJoinSequence(roleAlias, joinType);
      elem = createCollectionJoin(joinSequence, roleAlias);
    } else { // A collection of scalar elements...
      JoinSequence joinSequence = createJoinSequence(roleAlias, joinType);
      elem = createCollectionJoin(joinSequence, roleAlias);
    }

    elem.setRole(role);
    elem.setQueryableCollection(queryableCollection);
    // Don't include sub-classes for implied collection joins or subquery joins.
    if (implied) {
      elem.setIncludeSubclasses(false);
    }

    if (explicitSubqueryFromElement) {
      elem.setInProjectionList(true); // Treat explict from elements in sub-queries properly.
    }

    if (fetchFlag) {
      elem.setFetch(true);
    }
    return elem;
  }
Example #11
0
 private void addCollectionFromElement(FromElement fromElement) {
   if (fromElement.isFetch()) {
     if (fromElement.getQueryableCollection() != null) {
       String suffix;
       if (collectionFromElements == null) {
         collectionFromElements = new ArrayList();
         suffix = VERSION2_SQL ? "__" : "0__";
       } else {
         suffix = Integer.toString(collectionFromElements.size()) + "__";
       }
       collectionFromElements.add(fromElement);
       fromElement.setCollectionSuffix(suffix);
     }
   }
 }
  private FromElement createEntityAssociation(String role, String roleAlias, int joinType)
      throws SemanticException {
    FromElement elem;
    Queryable entityPersister = (Queryable) queryableCollection.getElementPersister();
    String associatedEntityName = entityPersister.getEntityName();
    // Get the class name of the associated entity.
    if (queryableCollection.isOneToMany()) {
      if (log.isDebugEnabled()) {
        log.debug(
            "createEntityAssociation() : One to many - path = "
                + path
                + " role = "
                + role
                + " associatedEntityName = "
                + associatedEntityName);
      }
      JoinSequence joinSequence = createJoinSequence(roleAlias, joinType);

      elem =
          createJoin(
              associatedEntityName,
              roleAlias,
              joinSequence,
              (EntityType) queryableCollection.getElementType(),
              false);
    } else {
      if (log.isDebugEnabled()) {
        log.debug(
            "createManyToMany() : path = "
                + path
                + " role = "
                + role
                + " associatedEntityName = "
                + associatedEntityName);
      }
      elem =
          createManyToMany(
              role,
              associatedEntityName,
              roleAlias,
              entityPersister,
              (EntityType) queryableCollection.getElementType(),
              joinType);
      fromClause.getWalker().addQuerySpaces(queryableCollection.getCollectionSpaces());
    }
    elem.setCollectionTableAlias(roleAlias);
    return elem;
  }
Example #13
0
 private void renderNonScalarIdentifiers(
     FromElement fromElement,
     int nonscalarSize,
     int j,
     SelectExpression expr,
     ASTAppender appender) {
   String text = fromElement.renderIdentifierSelect(nonscalarSize, j);
   if (!fromElement.getFromClause().isSubQuery()) {
     if (!scalarSelect && !getWalker().isShallowQuery()) {
       // TODO: is this a bit ugly?
       expr.setText(text);
     } else {
       appender.append(SqlTokenTypes.SQL_TOKEN, text, false);
     }
   }
 }
  private void handleElements(FromReferenceNode collectionNode, String propertyName) {
    FromElement collectionFromElement = collectionNode.getFromElement();
    QueryableCollection queryableCollection = collectionFromElement.getQueryableCollection();

    String path = collectionNode.getPath() + "[]." + propertyName;
    log.debug("Creating elements for " + path);

    fromElement = collectionFromElement;
    if (!collectionFromElement.isCollectionOfValuesOrComponents()) {
      getWalker().addQuerySpaces(queryableCollection.getElementPersister().getQuerySpaces());
    }

    setDataType(queryableCollection.getElementType());
    selectColumns =
        collectionFromElement.toColumns(fromElement.getTableAlias(), propertyName, inSelect);
  }
 public String getDisplayText() {
   return "{"
       + "method="
       + getMethodName()
       + ",selectColumns="
       + (selectColumns == null ? null : Arrays.asList(selectColumns))
       + ",fromElement="
       + fromElement.getTableAlias()
       + "}";
 }
  private FromElement createFromElementInSubselect(
      String path, String pathAlias, FromElement parentFromElement, String classAlias)
      throws SemanticException {
    if (log.isDebugEnabled()) {
      log.debug("createFromElementInSubselect() : path = " + path);
    }
    // Create an DotNode AST for the path and resolve it.
    FromElement fromElement = evaluateFromElementPath(path, classAlias);
    EntityPersister entityPersister = fromElement.getEntityPersister();

    // If the first identifier in the path referrs to the class alias (not the class name), then
    // this
    // is a correlated subselect.  If it's a correlated sub-select, use the existing table alias.
    // Otherwise
    // generate a new one.
    String tableAlias = null;
    boolean correlatedSubselect = pathAlias.equals(parentFromElement.getClassAlias());
    if (correlatedSubselect) {
      tableAlias = fromElement.getTableAlias();
    } else {
      tableAlias = null;
    }

    // If the from element isn't in the same clause, create a new from element.
    if (fromElement.getFromClause() != fromClause) {
      if (log.isDebugEnabled()) {
        log.debug("createFromElementInSubselect() : creating a new FROM element...");
      }
      fromElement = createFromElement(entityPersister);
      initializeAndAddFromElement(
          fromElement,
          path,
          classAlias,
          entityPersister,
          (EntityType) ((Queryable) entityPersister).getType(),
          tableAlias);
    }
    if (log.isDebugEnabled()) {
      log.debug("createFromElementInSubselect() : " + path + " -> " + fromElement);
    }
    return fromElement;
  }
 private void initializeAndAddFromElement(
     FromElement element,
     String className,
     String classAlias,
     EntityPersister entityPersister,
     EntityType type,
     String tableAlias) {
   if (tableAlias == null) {
     AliasGenerator aliasGenerator = fromClause.getAliasGenerator();
     tableAlias = aliasGenerator.createName(entityPersister.getEntityName());
   }
   element.initializeEntity(fromClause, className, entityPersister, type, classAlias, tableAlias);
 }
  FromElement createElementJoin(QueryableCollection queryableCollection) throws SemanticException {
    FromElement elem;

    implied =
        true; // TODO: always true for now, but not if we later decide to support elements() in the
              // from clause
    inElementsFunction = true;
    Type elementType = queryableCollection.getElementType();
    if (!elementType.isEntityType()) {
      throw new IllegalArgumentException(
          "Cannot create element join for a collection of non-entities!");
    }
    this.queryableCollection = queryableCollection;
    SessionFactoryHelper sfh = fromClause.getSessionFactoryHelper();
    FromElement destination = null;
    String tableAlias = null;
    EntityPersister entityPersister = queryableCollection.getElementPersister();
    tableAlias = fromClause.getAliasGenerator().createName(entityPersister.getEntityName());
    String associatedEntityName = entityPersister.getEntityName();
    EntityPersister targetEntityPersister = sfh.requireClassPersister(associatedEntityName);
    // Create the FROM element for the target (the elements of the collection).
    destination =
        createAndAddFromElement(
            associatedEntityName,
            classAlias,
            targetEntityPersister,
            (EntityType) queryableCollection.getElementType(),
            tableAlias);
    // If the join is implied, then don't include sub-classes on the element.
    if (implied) {
      destination.setIncludeSubclasses(false);
    }
    fromClause.addCollectionJoinFromElementByPath(path, destination);
    //		origin.addDestination(destination);
    // Add the query spaces.
    fromClause.getWalker().addQuerySpaces(entityPersister.getQuerySpaces());

    CollectionType type = queryableCollection.getCollectionType();
    String role = type.getRole();
    String roleAlias = origin.getTableAlias();

    String[] targetColumns = sfh.getCollectionElementColumns(role, roleAlias);
    AssociationType elementAssociationType = sfh.getElementAssociationType(type);

    // Create the join element under the from element.
    int joinType = JoinFragment.INNER_JOIN;
    JoinSequence joinSequence =
        sfh.createJoinSequence(
            implied, elementAssociationType, tableAlias, joinType, targetColumns);
    elem = initializeJoin(path, destination, joinSequence, targetColumns, origin, false);
    elem.setUseFromFragment(
        true); // The associated entity is implied, but it must be included in the FROM.
    elem.setCollectionTableAlias(roleAlias); // The collection alias is the role.
    return elem;
  }
Example #19
0
 private void renderNonScalarProperties(
     ASTAppender appender, FromElement fromElement, int nonscalarSize, int k) {
   String text = fromElement.renderPropertySelect(nonscalarSize, k);
   appender.append(SqlTokenTypes.SQL_TOKEN, text, false);
   if (fromElement.getQueryableCollection() != null && fromElement.isFetch()) {
     text = fromElement.renderCollectionSelectFragment(nonscalarSize, k);
     appender.append(SqlTokenTypes.SQL_TOKEN, text, false);
   }
   // Look through the FromElement's children to find any collections of values that should be
   // fetched...
   ASTIterator iter = new ASTIterator(fromElement);
   while (iter.hasNext()) {
     FromElement child = (FromElement) iter.next();
     if (child.isCollectionOfValuesOrComponents() && child.isFetch()) {
       // Need a better way to define the suffixes here...
       text = child.renderValueCollectionSelectFragment(nonscalarSize, nonscalarSize + k);
       appender.append(SqlTokenTypes.SQL_TOKEN, text, false);
     }
   }
 }
Example #20
0
 public boolean include(AST node) {
   FromElement fromElement = (FromElement) node;
   return fromElement.isFetch() && fromElement.getQueryableCollection() != null;
 }
Example #21
0
 public boolean include(AST node) {
   FromElement fromElement = (FromElement) node;
   return fromElement.inProjectionList();
 }
Example #22
0
 public boolean include(AST node) {
   FromElement fromElement = (FromElement) node;
   return fromElement.isFromOrJoinFragment();
 }
Example #23
0
 public boolean include(AST node) {
   final FromElement fromElement = (FromElement) node;
   return !fromElement.isImplied();
 }
  FromElement createEntityJoin(
      String entityClass,
      String tableAlias,
      JoinSequence joinSequence,
      boolean fetchFlag,
      boolean inFrom,
      EntityType type)
      throws SemanticException {
    FromElement elem = createJoin(entityClass, tableAlias, joinSequence, type, false);
    elem.setFetch(fetchFlag);
    EntityPersister entityPersister = elem.getEntityPersister();
    int numberOfTables = entityPersister.getQuerySpaces().length;
    if (numberOfTables > 1 && implied && !elem.useFromFragment()) {
      if (log.isDebugEnabled()) {
        log.debug("createEntityJoin() : Implied multi-table entity join");
      }
      elem.setUseFromFragment(true);
    }

    // If this is an implied join in a FROM clause, then use ANSI-style joining, and set the
    // flag on the FromElement that indicates that it was implied in the FROM clause itself.
    if (implied && inFrom) {
      joinSequence.setUseThetaStyle(false);
      elem.setUseFromFragment(true);
      elem.setImpliedInFromClause(true);
    }
    if (elem.getWalker().isSubQuery()) {
      // two conditions where we need to transform this to a theta-join syntax:
      //      1) 'elem' is the "root from-element" in correlated subqueries
      //      2) The DotNode.useThetaStyleImplicitJoins has been set to true
      //          and 'elem' represents an implicit join
      if (elem.getFromClause() != elem.getOrigin().getFromClause()
          ||
          //			        ( implied && DotNode.useThetaStyleImplicitJoins ) ) {
          DotNode.useThetaStyleImplicitJoins) {
        // the "root from-element" in correlated subqueries do need this piece
        elem.setType(FROM_FRAGMENT);
        joinSequence.setUseThetaStyle(true);
        elem.setUseFromFragment(false);
      }
    }

    return elem;
  }
Example #25
0
  /**
   * Prepares an explicitly defined select clause.
   *
   * @param fromClause The from clause linked to this select clause.
   * @throws SemanticException indicates a semntic issue with the explicit select clause.
   */
  public void initializeExplicitSelectClause(FromClause fromClause) throws SemanticException {
    if (prepared) {
      throw new IllegalStateException("SelectClause was already prepared!");
    }

    // explicit = true;	// This is an explict Select.
    // ArrayList sqlResultTypeList = new ArrayList();
    ArrayList queryReturnTypeList = new ArrayList();

    // First, collect all of the select expressions.
    // NOTE: This must be done *before* invoking setScalarColumnText() because setScalarColumnText()
    // changes the AST!!!
    SelectExpression[] selectExpressions = collectSelectExpressions();

    // we only support parameters in select in the case of INSERT...SELECT statements
    if (getParameterPositions().size() > 0
        && getWalker().getStatementType() != HqlSqlTokenTypes.INSERT) {
      throw new QueryException(
          "Parameters are only supported in SELECT clauses when used as part of a INSERT INTO DML statement");
    }

    for (int i = 0; i < selectExpressions.length; i++) {
      SelectExpression selectExpression = selectExpressions[i];

      if (AggregatedSelectExpression.class.isInstance(selectExpression)) {
        aggregatedSelectExpression = (AggregatedSelectExpression) selectExpression;
        queryReturnTypeList.addAll(aggregatedSelectExpression.getAggregatedSelectionTypeList());
        scalarSelect = true;
      } else {
        // we have no choice but to do this check here
        // this is not very elegant but the "right way" would most likely involve a bigger rewrite
        // so as to
        // treat ParameterNodes in select clauses as SelectExpressions
        boolean inSubquery =
            selectExpression instanceof QueryNode
                && ((QueryNode) selectExpression).getFromClause().getParentFromClause() != null;
        if (getWalker().getStatementType() == HqlSqlTokenTypes.INSERT && inSubquery) {
          // we do not support parameters for subqueries in INSERT...SELECT
          if (((QueryNode) selectExpression).getSelectClause().getParameterPositions().size() > 0) {
            throw new QueryException(
                "Use of parameters in subqueries of INSERT INTO DML statements is not supported.");
          }
        }

        Type type = selectExpression.getDataType();
        if (type == null) {
          throw new IllegalStateException(
              "No data type for node: "
                  + selectExpression.getClass().getName()
                  + " "
                  + new ASTPrinter(SqlTokenTypes.class).showAsString((AST) selectExpression, ""));
        }
        // sqlResultTypeList.add( type );

        // If the data type is not an association type, it could not have been in the FROM clause.
        if (selectExpression.isScalar()) {
          scalarSelect = true;
        }

        if (isReturnableEntity(selectExpression)) {
          fromElementsForLoad.add(selectExpression.getFromElement());
        }

        // Always add the type to the return type list.
        queryReturnTypeList.add(type);
      }
    }

    // init the aliases, after initing the constructornode
    initAliases(selectExpressions);

    if (!getWalker().isShallowQuery()) {
      // add the fetched entities
      List fromElements = fromClause.getProjectionList();

      ASTAppender appender =
          new ASTAppender(getASTFactory(), this); // Get ready to start adding nodes.
      int size = fromElements.size();

      Iterator iterator = fromElements.iterator();
      for (int k = 0; iterator.hasNext(); k++) {
        FromElement fromElement = (FromElement) iterator.next();

        if (fromElement.isFetch()) {
          FromElement origin = null;
          if (fromElement.getRealOrigin() == null) {
            // work around that crazy issue where the tree contains
            // "empty" FromElements (no text); afaict, this is caused
            // by FromElementFactory.createCollectionJoin()
            if (fromElement.getOrigin() == null) {
              throw new QueryException(
                  "Unable to determine origin of join fetch ["
                      + fromElement.getDisplayText()
                      + "]");
            } else {
              origin = fromElement.getOrigin();
            }
          } else {
            origin = fromElement.getRealOrigin();
          }
          if (!fromElementsForLoad.contains(origin)) {
            throw new QueryException(
                "query specified join fetching, but the owner "
                    + "of the fetched association was not present in the select list "
                    + "["
                    + fromElement.getDisplayText()
                    + "]");
          }
          Type type = fromElement.getSelectType();
          addCollectionFromElement(fromElement);
          if (type != null) {
            boolean collectionOfElements = fromElement.isCollectionOfValuesOrComponents();
            if (!collectionOfElements) {
              // Add the type to the list of returned sqlResultTypes.
              fromElement.setIncludeSubclasses(true);
              fromElementsForLoad.add(fromElement);
              // sqlResultTypeList.add( type );
              // Generate the select expression.
              String text = fromElement.renderIdentifierSelect(size, k);
              SelectExpressionImpl generatedExpr =
                  (SelectExpressionImpl) appender.append(SqlTokenTypes.SELECT_EXPR, text, false);
              if (generatedExpr != null) {
                generatedExpr.setFromElement(fromElement);
              }
            }
          }
        }
      }

      // generate id select fragment and then property select fragment for
      // each expression, just like generateSelectFragments().
      renderNonScalarSelects(collectSelectExpressions(), fromClause);
    }

    if (scalarSelect || getWalker().isShallowQuery()) {
      // If there are any scalars (non-entities) selected, render the select column aliases.
      renderScalarSelects(selectExpressions, fromClause);
    }

    finishInitialization(/*sqlResultTypeList,*/ queryReturnTypeList);
  }