private FromElement createManyToMany(
     String role,
     String associatedEntityName,
     String roleAlias,
     Queryable entityPersister,
     EntityType type,
     JoinType 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;
 }
  private void addJoinNodes(QueryNode query, JoinSequence join, FromElement fromElement) {
    JoinFragment joinFragment =
        join.toJoinFragment(
            walker.getEnabledFilters(),
            fromElement.useFromFragment()
                || fromElement.isDereferencedBySuperclassOrSubclassProperty(),
            fromElement.getWithClauseFragment(),
            fromElement.getWithClauseJoinAlias());

    String frag = joinFragment.toFromFragmentString();
    String whereFrag = joinFragment.toWhereFragmentString();

    // If the from element represents a JOIN_FRAGMENT and it is
    // a theta-style join, convert its type from JOIN_FRAGMENT
    // to FROM_FRAGMENT
    if (fromElement.getType() == JOIN_FRAGMENT
        && (join.isThetaStyle() || StringHelper.isNotEmpty(whereFrag))) {
      fromElement.setType(FROM_FRAGMENT);
      fromElement
          .getJoinSequence()
          .setUseThetaStyle(true); // this is used during SqlGenerator processing
    }

    // If there is a FROM fragment and the FROM element is an explicit, then add the from part.
    if (fromElement.useFromFragment() /*&& StringHelper.isNotEmpty( frag )*/) {
      String fromFragment = processFromFragment(frag, join).trim();
      LOG.debugf("Using FROM fragment [%s]", fromFragment);
      processDynamicFilterParameters(fromFragment, fromElement, walker);
    }

    syntheticAndFactory.addWhereFragment(joinFragment, whereFrag, query, fromElement, walker);
  }
  private void prepareForIndex(QueryTranslatorImpl q) throws QueryException {

    QueryableCollection collPersister = q.getCollectionPersister(collectionRole);

    if (!collPersister.hasIndex())
      throw new QueryException("unindexed collection before []: " + path);
    String[] indexCols = collPersister.getIndexColumnNames();
    if (indexCols.length != 1) throw new QueryException("composite-index appears in []: " + path);
    // String[] keyCols = collPersister.getKeyColumnNames();

    JoinSequence fromJoins =
        new JoinSequence(q.getFactory())
            .setUseThetaStyle(useThetaStyleJoin)
            .setRoot(collPersister, collectionName)
            .setNext(joinSequence.copy());

    if (!continuation) addJoin(collectionName, collPersister.getCollectionType());

    joinSequence.addCondition(
        collectionName + '.' + indexCols[0] + " = "); // TODO: get SQL rendering out of here

    CollectionElement elem = new CollectionElement();
    elem.elementColumns = collPersister.getElementColumnNames(collectionName);
    elem.elementType = collPersister.getElementType();
    elem.isOneToMany = collPersister.isOneToMany();
    elem.alias = collectionName;
    elem.joinSequence = joinSequence;
    collectionElements.addLast(elem);
    setExpectingCollectionIndex();

    q.addCollection(collectionName, collectionRole);
    q.addFromJoinOnly(collectionName, fromJoins);
  }
  public void processJoins(QueryNode query) {
    final FromClause fromClause = query.getFromClause();

    final List fromElements;
    if (DotNode.useThetaStyleImplicitJoins) {
      // for regression testing against output from the old parser...
      // found it easiest to simply reorder the FromElements here into ascending order
      // in terms of injecting them into the resulting sql ast in orders relative to those
      // expected by the old parser; this is definitely another of those "only needed
      // for regression purposes".  The SyntheticAndFactory, then, simply injects them as it
      // encounters them.
      fromElements = new ArrayList();
      ListIterator liter =
          fromClause.getFromElements().listIterator(fromClause.getFromElements().size());
      while (liter.hasPrevious()) {
        fromElements.add(liter.previous());
      }
    } else {
      fromElements = fromClause.getFromElements();
    }

    // Iterate through the alias,JoinSequence pairs and generate SQL token nodes.
    Iterator iter = fromElements.iterator();
    while (iter.hasNext()) {
      final FromElement fromElement = (FromElement) iter.next();
      JoinSequence join = fromElement.getJoinSequence();
      join.setSelector(
          new JoinSequence.Selector() {
            public boolean includeSubclasses(String alias) {
              // The uber-rule here is that we need to include subclass joins if
              // the FromElement is in any way dereferenced by a property from
              // the subclass table; otherwise we end up with column references
              // qualified by a non-existent table reference in the resulting SQL...
              boolean containsTableAlias = fromClause.containsTableAlias(alias);
              if (fromElement.isDereferencedBySubclassProperty()) {
                // TODO : or should we return 'containsTableAlias'??
                LOG.trace(
                    "Forcing inclusion of extra joins [alias="
                        + alias
                        + ", containsTableAlias="
                        + containsTableAlias
                        + "]");
                return true;
              }
              boolean shallowQuery = walker.isShallowQuery();
              boolean includeSubclasses = fromElement.isIncludeSubclasses();
              boolean subQuery = fromClause.isSubQuery();
              return includeSubclasses && containsTableAlias && !subQuery && !shallowQuery;
            }
          });
      addJoinNodes(query, join, fromElement);
    }
  }
  public FromElement createEntityJoin(
      String entityClass,
      String tableAlias,
      JoinSequence joinSequence,
      boolean fetchFlag,
      boolean inFrom,
      EntityType type,
      String role,
      String joinPath)
      throws SemanticException {
    FromElement elem = createJoin(entityClass, tableAlias, joinSequence, type, false);
    elem.setFetch(fetchFlag);

    if (joinPath != null) {
      elem.applyTreatAsDeclarations(fromClause.getWalker().getTreatAsDeclarationsByPath(joinPath));
    }

    EntityPersister entityPersister = elem.getEntityPersister();
    int numberOfTables = entityPersister.getQuerySpaces().length;
    if (numberOfTables > 1 && implied && !elem.useFromFragment()) {
      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 ) ) {
          PathSeparatorNode.useThetaStyleImplicitJoins) {
        // the "root from-element" in correlated subqueries do need this piece
        elem.setType(FROM_FRAGMENT);
        joinSequence.setUseThetaStyle(true);
        elem.setUseFromFragment(false);
      }
    }

    elem.setRole(role);

    return elem;
  }
 private void addJoin(String name, AssociationType joinableType) throws QueryException {
   try {
     joinSequence.addJoin(joinableType, name, joinType, currentColumns());
   } catch (MappingException me) {
     throw new QueryException(me);
   }
 }
 private void addJoin(String name, AssociationType joinableType, String[] foreignKeyColumns)
     throws QueryException {
   try {
     joinSequence.addJoin(joinableType, name, joinType, foreignKeyColumns);
   } catch (MappingException me) {
     throw new QueryException(me);
   }
 }
Beispiel #8
0
 private void addJoin(JoinSequence joinSequence, QueryTranslatorImpl q) throws QueryException {
   // JoinFragment fromClause = q.createJoinFragment(true);
   // fromClause.addJoins( join.toJoinFragment().toFromFragmentString(), StringHelper.EMPTY_STRING
   // );
   q.addFromJoinOnly(pathExpressionParser.getName(), joinSequence);
   try {
     addToCurrentJoin(
         joinSequence.toJoinFragment(q.getEnabledFilters(), true).toWhereFragmentString());
   } catch (MappingException me) {
     throw new QueryException(me);
   }
 }
  /** Used for collection filters */
  private void addFromAssociation(final String elementName, final String collectionRole)
      throws QueryException {
    // q.addCollection(collectionName, collectionRole);
    QueryableCollection persister = getCollectionPersister(collectionRole);
    Type collectionElementType = persister.getElementType();
    if (!collectionElementType.isEntityType()) {
      throw new QueryException("collection of values in filter: " + elementName);
    }

    String[] keyColumnNames = persister.getKeyColumnNames();
    // if (keyColumnNames.length!=1) throw new QueryException("composite-key collection in filter: "
    // + collectionRole);

    String collectionName;
    JoinSequence join = new JoinSequence(getFactory());
    collectionName =
        persister.isOneToMany() ? elementName : createNameForCollection(collectionRole);
    join.setRoot(persister, collectionName);
    if (!persister.isOneToMany()) {
      // many-to-many
      addCollection(collectionName, collectionRole);
      try {
        join.addJoin(
            (AssociationType) persister.getElementType(),
            elementName,
            JoinType.INNER_JOIN,
            persister.getElementColumnNames(collectionName));
      } catch (MappingException me) {
        throw new QueryException(me);
      }
    }
    join.addCondition(collectionName, keyColumnNames, " = ?");
    // if ( persister.hasWhere() ) join.addCondition( persister.getSQLWhereString(collectionName) );
    EntityType elemType = (EntityType) collectionElementType;
    addFrom(elementName, elemType.getAssociatedEntityName(), join);
  }
  private void mergeJoins(JoinFragment ojf) throws MappingException, QueryException {

    Iterator iter = joins.entrySet().iterator();
    while (iter.hasNext()) {
      Map.Entry me = (Map.Entry) iter.next();
      String name = (String) me.getKey();
      JoinSequence join = (JoinSequence) me.getValue();
      join.setSelector(
          new JoinSequence.Selector() {
            public boolean includeSubclasses(String alias) {
              boolean include = returnedTypes.contains(alias) && !isShallowQuery();
              return include;
            }
          });

      if (typeMap.containsKey(name)) {
        ojf.addFragment(join.toJoinFragment(enabledFilters, true));
      } else if (collections.containsKey(name)) {
        ojf.addFragment(join.toJoinFragment(enabledFilters, true));
      } else {
        // name from a super query (a bit inelegant that it shows up here)
      }
    }
  }
 public static String createCollectionSubquery(
     JoinSequence joinSequence, Map enabledFilters, String[] columns) {
   try {
     JoinFragment join = joinSequence.toJoinFragment(enabledFilters, true);
     return new StringBuilder("select ")
         .append(StringHelper.join(", ", columns))
         .append(" from ")
         .append(join.toFromFragmentString().substring(2)) // remove initial ", "
         .append(" where ")
         .append(join.toWhereFragmentString().substring(5)) // remove initial " and "
         .toString();
   } catch (MappingException me) {
     throw new QueryException(me);
   }
 }
  private void dereferenceEntity(
      String propertyName, EntityType propertyType, QueryTranslatorImpl q) throws QueryException {
    // NOTE: we avoid joining to the next table if the named property is just the foreign key value

    // if its "id"
    boolean isIdShortcut =
        EntityPersister.ENTITY_ID.equals(propertyName) && propertyType.isReferenceToPrimaryKey();

    // or its the id property name
    final String idPropertyName;
    try {
      idPropertyName = propertyType.getIdentifierOrUniqueKeyPropertyName(q.getFactory());
    } catch (MappingException me) {
      throw new QueryException(me);
    }
    boolean isNamedIdPropertyShortcut =
        idPropertyName != null
            && idPropertyName.equals(propertyName)
            && propertyType.isReferenceToPrimaryKey();

    if (isIdShortcut || isNamedIdPropertyShortcut) {
      // special shortcut for id properties, skip the join!
      // this must only occur at the _end_ of a path expression
      if (componentPath.length() > 0) componentPath.append('.');
      componentPath.append(propertyName);
    } else {
      String entityClass = propertyType.getAssociatedEntityName();
      String name = q.createNameFor(entityClass);
      q.addType(name, entityClass);
      addJoin(name, propertyType);
      if (propertyType.isOneToOne()) oneToOneOwnerName = currentName;
      ownerAssociationType = propertyType;
      currentName = name;
      currentProperty = propertyName;
      q.addPathAliasAndJoin(
          path.substring(0, path.toString().lastIndexOf('.')), name, joinSequence.copy());
      componentPath.setLength(0);
      currentPropertyMapping = q.getEntityPersister(entityClass);
    }
  }
 void addFromJoinOnly(String name, JoinSequence joinSequence) throws QueryException {
   addJoin(name, joinSequence.getFromPart());
 }
  public void token(String token, QueryTranslatorImpl q) throws QueryException {

    if (token != null) path.append(token);

    String alias = q.getPathAlias(path.toString());
    if (alias != null) {
      reset(q); // reset the dotcount (but not the path)
      currentName = alias; // after reset!
      currentPropertyMapping = q.getPropertyMapping(currentName);
      if (!ignoreInitialJoin) {
        JoinSequence ojf = q.getPathJoin(path.toString());
        try {
          joinSequence.addCondition(
              ojf.toJoinFragment(q.getEnabledFilters(), true)
                  .toWhereFragmentString()); // after reset!
        } catch (MappingException me) {
          throw new QueryException(me);
        }
        // we don't need to worry about any condition in the ON clause
        // here (toFromFragmentString), since anything in the ON condition
        // is already applied to the whole query
      }
    } else if (".".equals(token)) {
      dotcount++;
    } else {
      if (dotcount == 0) {
        if (!continuation) {
          if (!q.isName(token)) throw new QueryException("undefined alias: " + token);
          currentName = token;
          currentPropertyMapping = q.getPropertyMapping(currentName);
        }
      } else if (dotcount == 1) {
        if (currentName != null) {
          currentProperty = token;
        } else if (collectionName != null) {
          // processCollectionProperty(token, q.getCollectionPersister(collectionRole),
          // collectionName);
          continuation = false;
        } else {
          throw new QueryException("unexpected");
        }
      } else { // dotcount>=2

        // Do the corresponding RHS
        Type propertyType = getPropertyType();

        if (propertyType == null) {
          throw new QueryException("unresolved property: " + path);
        }

        if (propertyType.isComponentType()) {
          dereferenceComponent(token);
        } else if (propertyType.isEntityType()) {
          if (!isCollectionValued()) dereferenceEntity(token, (EntityType) propertyType, q);
        } else if (propertyType.isCollectionType()) {
          dereferenceCollection(token, ((CollectionType) propertyType).getRole(), q);

        } else {
          if (token != null) throw new QueryException("dereferenced: " + path);
        }
      }
    }
  }