Search in sources :

Example 11 with JoinSequence

use of org.hibernate.engine.internal.JoinSequence in project hibernate-orm by hibernate.

the class QueryTranslatorImpl method addFromAssociation.

/**
	 * 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);
}
Also used : EntityType(org.hibernate.type.EntityType) JoinType(org.hibernate.sql.JoinType) EntityType(org.hibernate.type.EntityType) AssociationType(org.hibernate.type.AssociationType) Type(org.hibernate.type.Type) QueryException(org.hibernate.QueryException) QueryableCollection(org.hibernate.persister.collection.QueryableCollection) JoinSequence(org.hibernate.engine.internal.JoinSequence) MappingException(org.hibernate.MappingException)

Example 12 with JoinSequence

use of org.hibernate.engine.internal.JoinSequence in project hibernate-orm by hibernate.

the class QueryTranslatorImpl method mergeJoins.

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() {

            @Override
            public boolean includeSubclasses(String alias) {
                return returnedTypes.contains(alias) && !isShallowQuery();
            }
        });
        if (typeMap.containsKey(name)) {
            ojf.addFragment(join.toJoinFragment(enabledFilters, true));
        } else if (collections.containsKey(name)) {
            ojf.addFragment(join.toJoinFragment(enabledFilters, true));
        }
    }
}
Also used : Iterator(java.util.Iterator) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) JoinSequence(org.hibernate.engine.internal.JoinSequence)

Example 13 with JoinSequence

use of org.hibernate.engine.internal.JoinSequence in project hibernate-orm by hibernate.

the class JoinProcessor method processJoins.

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 = new ArrayList(fromClause.getFromElements().size());
        ListIterator<FromElement> liter = fromClause.getFromElements().listIterator();
        while (liter.hasNext()) {
            FromElement fromElement = liter.next();
            // We found an implied from element that is used in the WITH clause of another from element, so it need to become part of it's join sequence
            if (fromElement instanceof ImpliedFromElement && fromElement.getOrigin().getWithClauseFragment() != null && fromElement.getOrigin().getWithClauseFragment().contains(fromElement.getTableAlias())) {
                fromElement.getOrigin().getJoinSequence().addJoin((ImpliedFromElement) fromElement);
                // This from element will be rendered as part of the origins join sequence
                fromElement.setText("");
            } else {
                fromElements.add(fromElement);
            }
        }
    }
    // 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.tracev("Forcing inclusion of extra joins [alias={0}, containsTableAlias={1}]", alias, containsTableAlias);
                    return true;
                }
                boolean shallowQuery = walker.isShallowQuery();
                boolean includeSubclasses = fromElement.isIncludeSubclasses();
                boolean subQuery = fromClause.isSubQuery();
                return includeSubclasses && containsTableAlias && !subQuery && !shallowQuery;
            }
        });
        addJoinNodes(query, join, fromElement);
    }
}
Also used : FromClause(org.hibernate.hql.internal.ast.tree.FromClause) FromElement(org.hibernate.hql.internal.ast.tree.FromElement) ImpliedFromElement(org.hibernate.hql.internal.ast.tree.ImpliedFromElement) ArrayList(java.util.ArrayList) ListIterator(java.util.ListIterator) Iterator(java.util.Iterator) ArrayList(java.util.ArrayList) List(java.util.List) ImpliedFromElement(org.hibernate.hql.internal.ast.tree.ImpliedFromElement) ListIterator(java.util.ListIterator) JoinSequence(org.hibernate.engine.internal.JoinSequence)

Example 14 with JoinSequence

use of org.hibernate.engine.internal.JoinSequence in project hibernate-orm by hibernate.

the class IndexNode method resolve.

@Override
public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent, AST parentPredicate) throws SemanticException {
    if (isResolved()) {
        return;
    }
    FromReferenceNode collectionNode = (FromReferenceNode) getFirstChild();
    SessionFactoryHelper sessionFactoryHelper = getSessionFactoryHelper();
    // Fully resolve the map reference, create implicit joins.
    collectionNode.resolveIndex(this);
    Type type = collectionNode.getDataType();
    if (!type.isCollectionType()) {
        throw new SemanticException("The [] operator cannot be applied to type " + type.toString());
    }
    String collectionRole = ((CollectionType) type).getRole();
    QueryableCollection queryableCollection = sessionFactoryHelper.requireQueryableCollection(collectionRole);
    if (!queryableCollection.hasIndex()) {
        throw new QueryException("unindexed fromElement beforeQuery []: " + collectionNode.getPath());
    }
    // Generate the inner join -- The elements need to be joined to the collection they are in.
    FromElement fromElement = collectionNode.getFromElement();
    String elementTable = fromElement.getTableAlias();
    FromClause fromClause = fromElement.getFromClause();
    String path = collectionNode.getPath();
    FromElement elem = fromClause.findCollectionJoin(path);
    if (elem == null) {
        FromElementFactory factory = new FromElementFactory(fromClause, fromElement, path);
        elem = factory.createCollectionElementsJoin(queryableCollection, elementTable);
        LOG.debugf("No FROM element found for the elements of collection join path %s, created %s", path, elem);
    } else {
        LOG.debugf("FROM element found for collection join path %s", path);
    }
    // The 'from element' that represents the elements of the collection.
    setFromElement(fromElement);
    // Add the condition to the join sequence that qualifies the indexed element.
    AST selector = collectionNode.getNextSibling();
    if (selector == null) {
        throw new QueryException("No index value!");
    }
    // Sometimes use the element table alias, sometimes use the... umm... collection table alias (many to many)
    String collectionTableAlias = elementTable;
    if (elem.getCollectionTableAlias() != null) {
        collectionTableAlias = elem.getCollectionTableAlias();
    }
    // TODO: get SQL rendering out of here, create an AST for the join expressions.
    // Use the SQL generator grammar to generate the SQL text for the index expression.
    JoinSequence joinSequence = fromElement.getJoinSequence();
    String[] indexCols = queryableCollection.getIndexColumnNames();
    if (indexCols.length != 1) {
        throw new QueryException("composite-index appears in []: " + collectionNode.getPath());
    }
    SqlGenerator gen = new SqlGenerator(getSessionFactoryHelper().getFactory());
    try {
        //TODO: used to be exprNoParens! was this needed?
        gen.simpleExpr(selector);
    } catch (RecognitionException e) {
        throw new QueryException(e.getMessage(), e);
    }
    String selectorExpression = gen.getSQL();
    joinSequence.addCondition(collectionTableAlias + '.' + indexCols[0] + " = " + selectorExpression);
    List<ParameterSpecification> paramSpecs = gen.getCollectedParameters();
    if (paramSpecs != null) {
        switch(paramSpecs.size()) {
            case 0:
                // nothing to do
                break;
            case 1:
                ParameterSpecification paramSpec = paramSpecs.get(0);
                paramSpec.setExpectedType(queryableCollection.getIndexType());
                fromElement.setIndexCollectionSelectorParamSpec(paramSpec);
                break;
            default:
                fromElement.setIndexCollectionSelectorParamSpec(new AggregatedIndexCollectionSelectorParameterSpecifications(paramSpecs));
                break;
        }
    }
    // Now, set the text for this node.  It should be the element columns.
    String[] elementColumns = queryableCollection.getElementColumnNames(elementTable);
    setText(elementColumns[0]);
    setResolved();
}
Also used : AST(antlr.collections.AST) ParameterSpecification(org.hibernate.param.ParameterSpecification) SessionFactoryHelper(org.hibernate.hql.internal.ast.util.SessionFactoryHelper) QueryableCollection(org.hibernate.persister.collection.QueryableCollection) CollectionType(org.hibernate.type.CollectionType) Type(org.hibernate.type.Type) QueryException(org.hibernate.QueryException) SqlGenerator(org.hibernate.hql.internal.ast.SqlGenerator) CollectionType(org.hibernate.type.CollectionType) JoinSequence(org.hibernate.engine.internal.JoinSequence) RecognitionException(antlr.RecognitionException) SemanticException(antlr.SemanticException)

Example 15 with JoinSequence

use of org.hibernate.engine.internal.JoinSequence in project hibernate-orm by hibernate.

the class DotNode method dereferenceEntityJoin.

private void dereferenceEntityJoin(String classAlias, EntityType propertyType, boolean impliedJoin, AST parent) throws SemanticException {
    dereferenceType = DereferenceType.ENTITY;
    if (LOG.isDebugEnabled()) {
        LOG.debugf("dereferenceEntityJoin() : generating join for %s in %s (%s) parent = %s", propertyName, getFromElement().getClassName(), classAlias == null ? "<no alias>" : classAlias, ASTUtil.getDebugString(parent));
    }
    // Create a new FROM node for the referenced class.
    String associatedEntityName = propertyType.getAssociatedEntityName();
    String tableAlias = getAliasGenerator().createName(associatedEntityName);
    String[] joinColumns = getColumns();
    String joinPath = getPath();
    if (impliedJoin && getWalker().isInFrom()) {
        joinType = getWalker().getImpliedJoinType();
    }
    FromClause currentFromClause = getWalker().getCurrentFromClause();
    FromElement elem = currentFromClause.findJoinByPath(joinPath);
    ///////////////////////////////////////////////////////////////////////////////
    //
    // This is the piece which recognizes the condition where an implicit join path
    // resolved earlier in a correlated subquery is now being referenced in the
    // outer query.  For 3.0final, we just let this generate a second join (which
    // is exactly how the old parser handles this).  Eventually we need to add this
    // logic back in and complete the logic in FromClause.promoteJoin; however,
    // FromClause.promoteJoin has its own difficulties (see the comments in
    // FromClause.promoteJoin).
    //
    //		if ( elem == null ) {
    //			// see if this joinPath has been used in a "child" FromClause, and if so
    //			// promote that element to the outer query
    //			FromClause currentNodeOwner = getFromElement().getFromClause();
    //			FromClause currentJoinOwner = currentNodeOwner.locateChildFromClauseWithJoinByPath( joinPath );
    //			if ( currentJoinOwner != null && currentNodeOwner != currentJoinOwner ) {
    //				elem = currentJoinOwner.findJoinByPathLocal( joinPath );
    //				if ( elem != null ) {
    //					currentFromClause.promoteJoin( elem );
    //					// EARLY EXIT!!!
    //					return;
    //				}
    //			}
    //		}
    //
    ///////////////////////////////////////////////////////////////////////////////
    boolean found = elem != null;
    // even though we might find a pre-existing element by join path, we may not be able to reuse it...
    boolean useFoundFromElement = found && canReuse(classAlias, elem);
    if (!useFoundFromElement) {
        // If this is an implied join in a from element, then use the impled join type which is part of the
        // tree parser's state (set by the gramamar actions).
        JoinSequence joinSequence = getSessionFactoryHelper().createJoinSequence(impliedJoin, propertyType, tableAlias, joinType, joinColumns);
        // If the lhs of the join is a "component join", we need to go back to the
        // first non-component-join as the origin to properly link aliases and
        // join columns
        FromElement lhsFromElement = getLhs().getFromElement();
        while (lhsFromElement != null && ComponentJoin.class.isInstance(lhsFromElement)) {
            lhsFromElement = lhsFromElement.getOrigin();
        }
        if (lhsFromElement == null) {
            throw new QueryException("Unable to locate appropriate lhs");
        }
        String role = lhsFromElement.getClassName() + "." + propertyName;
        FromElementFactory factory = new FromElementFactory(currentFromClause, lhsFromElement, joinPath, classAlias, joinColumns, impliedJoin);
        elem = factory.createEntityJoin(associatedEntityName, tableAlias, joinSequence, fetch, getWalker().isInFrom(), propertyType, role, joinPath);
    } else {
        // NOTE : addDuplicateAlias() already performs nullness checks on the alias.
        currentFromClause.addDuplicateAlias(classAlias, elem);
    }
    setImpliedJoin(elem);
    getWalker().addQuerySpaces(elem.getEntityPersister().getQuerySpaces());
    // This 'dot' expression now refers to the resulting from element.
    setFromElement(elem);
}
Also used : QueryException(org.hibernate.QueryException) JoinSequence(org.hibernate.engine.internal.JoinSequence)

Aggregations

JoinSequence (org.hibernate.engine.internal.JoinSequence)19 EntityType (org.hibernate.type.EntityType)7 Type (org.hibernate.type.Type)7 QueryException (org.hibernate.QueryException)6 QueryableCollection (org.hibernate.persister.collection.QueryableCollection)6 JoinType (org.hibernate.sql.JoinType)6 CollectionType (org.hibernate.type.CollectionType)5 SessionFactoryHelper (org.hibernate.hql.internal.ast.util.SessionFactoryHelper)4 AssociationType (org.hibernate.type.AssociationType)4 FromElement (org.hibernate.hql.internal.ast.tree.FromElement)3 ArrayList (java.util.ArrayList)2 Iterator (java.util.Iterator)2 MappingException (org.hibernate.MappingException)2 FromClause (org.hibernate.hql.internal.ast.tree.FromClause)2 ImpliedFromElement (org.hibernate.hql.internal.ast.tree.ImpliedFromElement)2 EntityPersister (org.hibernate.persister.entity.EntityPersister)2 CompositeType (org.hibernate.type.CompositeType)2 RecognitionException (antlr.RecognitionException)1 SemanticException (antlr.SemanticException)1 AST (antlr.collections.AST)1