Search in sources :

Example 1 with QueryNode

use of org.hibernate.hql.internal.ast.tree.QueryNode in project hibernate-orm by hibernate.

the class QueryTranslatorImpl method list.

@Override
public List list(SharedSessionContractImplementor session, QueryParameters queryParameters) throws HibernateException {
    // Delegate to the QueryLoader...
    errorIfDML();
    final QueryNode query = (QueryNode) sqlAst;
    final boolean hasLimit = queryParameters.getRowSelection() != null && queryParameters.getRowSelection().definesLimits();
    final boolean needsDistincting = (query.getSelectClause().isDistinct() || hasLimit) && containsCollectionFetches();
    QueryParameters queryParametersToUse;
    if (hasLimit && containsCollectionFetches()) {
        LOG.firstOrMaxResultsSpecifiedWithCollectionFetch();
        RowSelection selection = new RowSelection();
        selection.setFetchSize(queryParameters.getRowSelection().getFetchSize());
        selection.setTimeout(queryParameters.getRowSelection().getTimeout());
        queryParametersToUse = queryParameters.createCopyUsing(selection);
    } else {
        queryParametersToUse = queryParameters;
    }
    List results = queryLoader.list(session, queryParametersToUse);
    if (needsDistincting) {
        int includedCount = -1;
        // NOTE : firstRow is zero-based
        int first = !hasLimit || queryParameters.getRowSelection().getFirstRow() == null ? 0 : queryParameters.getRowSelection().getFirstRow();
        int max = !hasLimit || queryParameters.getRowSelection().getMaxRows() == null ? -1 : queryParameters.getRowSelection().getMaxRows();
        List tmp = new ArrayList();
        IdentitySet distinction = new IdentitySet();
        for (final Object result : results) {
            if (!distinction.add(result)) {
                continue;
            }
            includedCount++;
            if (includedCount < first) {
                continue;
            }
            tmp.add(result);
            // NOTE : ( max - 1 ) because first is zero-based while max is not...
            if (max >= 0 && (includedCount - first) >= (max - 1)) {
                break;
            }
        }
        results = tmp;
    }
    return results;
}
Also used : QueryNode(org.hibernate.hql.internal.ast.tree.QueryNode) IdentitySet(org.hibernate.internal.util.collections.IdentitySet) ArrayList(java.util.ArrayList) List(java.util.List) ArrayList(java.util.ArrayList) QueryParameters(org.hibernate.engine.spi.QueryParameters) RowSelection(org.hibernate.engine.spi.RowSelection) EntityGraphQueryHint(org.hibernate.engine.query.spi.EntityGraphQueryHint)

Example 2 with QueryNode

use of org.hibernate.hql.internal.ast.tree.QueryNode in project hibernate-orm by hibernate.

the class QueryTranslatorImpl method validateScrollability.

@Override
public void validateScrollability() throws HibernateException {
    // Impl Note: allows multiple collection fetches as long as the
    // entire fecthed graph still "points back" to a single
    // root entity for return
    errorIfDML();
    final QueryNode query = (QueryNode) sqlAst;
    // If there are no collection fetches, then no further checks are needed
    List collectionFetches = query.getFromClause().getCollectionFetches();
    if (collectionFetches.isEmpty()) {
        return;
    }
    // A shallow query is ok (although technically there should be no fetching here...)
    if (isShallowQuery()) {
        return;
    }
    // Make sure that there is only a single root entity in the return (no tuples)
    if (getReturnTypes().length > 1) {
        throw new HibernateException("cannot scroll with collection fetches and returned tuples");
    }
    FromElement owner = null;
    for (Object o : query.getSelectClause().getFromElementsForLoad()) {
        // should be the first, but just to be safe...
        final FromElement fromElement = (FromElement) o;
        if (fromElement.getOrigin() == null) {
            owner = fromElement;
            break;
        }
    }
    if (owner == null) {
        throw new HibernateException("unable to locate collection fetch(es) owner for scrollability checks");
    }
    // This is not strictly true.  We actually just need to make sure that
    // it is ordered by root-entity PK and that that order-by comes beforeQuery
    // any non-root-entity ordering...
    AST primaryOrdering = query.getOrderByClause().getFirstChild();
    if (primaryOrdering != null) {
        // TODO : this is a bit dodgy, come up with a better way to check this (plus see above comment)
        String[] idColNames = owner.getQueryable().getIdentifierColumnNames();
        String expectedPrimaryOrderSeq = StringHelper.join(", ", StringHelper.qualify(owner.getTableAlias(), idColNames));
        if (!primaryOrdering.getText().startsWith(expectedPrimaryOrderSeq)) {
            throw new HibernateException("cannot scroll results with collection fetches which are not ordered primarily by the root entity's PK");
        }
    }
}
Also used : AST(antlr.collections.AST) HibernateException(org.hibernate.HibernateException) QueryNode(org.hibernate.hql.internal.ast.tree.QueryNode) FromElement(org.hibernate.hql.internal.ast.tree.FromElement) List(java.util.List) ArrayList(java.util.ArrayList)

Example 3 with QueryNode

use of org.hibernate.hql.internal.ast.tree.QueryNode in project hibernate-orm by hibernate.

the class HqlSqlWalker method processQuery.

@Override
protected void processQuery(AST select, AST query) throws SemanticException {
    if (LOG.isDebugEnabled()) {
        LOG.debugf("processQuery() : %s", query.toStringTree());
    }
    try {
        QueryNode qn = (QueryNode) query;
        // Was there an explicit select expression?
        boolean explicitSelect = select != null && select.getNumberOfChildren() > 0;
        // Add in the EntityGraph attribute nodes.
        if (queryTranslatorImpl.getEntityGraphQueryHint() != null) {
            final boolean oldInEntityGraph = inEntityGraph;
            try {
                inEntityGraph = true;
                qn.getFromClause().getFromElements().addAll(queryTranslatorImpl.getEntityGraphQueryHint().toFromElements(qn.getFromClause(), this));
            } finally {
                inEntityGraph = oldInEntityGraph;
            }
        }
        if (!explicitSelect) {
            // No explicit select expression; render the id and properties
            // projection lists for every persister in the from clause into
            // a single 'token node'.
            //TODO: the only reason we need this stuff now is collection filters,
            //      we should get rid of derived select clause completely!
            createSelectClauseFromFromClause(qn);
        } else {
            // Use the explicitly declared select expression; determine the
            // return types indicated by each select token
            useSelectClause(select);
        }
        // After that, process the JOINs.
        // Invoke a delegate to do the work, as this is farily complex.
        JoinProcessor joinProcessor = new JoinProcessor(this);
        joinProcessor.processJoins(qn);
        // Attach any mapping-defined "ORDER BY" fragments
        Iterator itr = qn.getFromClause().getProjectionList().iterator();
        while (itr.hasNext()) {
            final FromElement fromElement = (FromElement) itr.next();
            //			if ( fromElement.isFetch() && fromElement.isCollectionJoin() ) {
            if (fromElement.isFetch() && fromElement.getQueryableCollection() != null) {
                // the query's order-by
                if (fromElement.getQueryableCollection().hasOrdering()) {
                    String orderByFragment = fromElement.getQueryableCollection().getSQLOrderByString(fromElement.getCollectionTableAlias());
                    qn.getOrderByClause().addOrderFragment(orderByFragment);
                }
                if (fromElement.getQueryableCollection().hasManyToManyOrdering()) {
                    String orderByFragment = fromElement.getQueryableCollection().getManyToManyOrderByString(fromElement.getTableAlias());
                    qn.getOrderByClause().addOrderFragment(orderByFragment);
                }
            }
        }
    } finally {
        popFromClause();
    }
}
Also used : QueryNode(org.hibernate.hql.internal.ast.tree.QueryNode) FromElement(org.hibernate.hql.internal.ast.tree.FromElement) EntityJoinFromElement(org.hibernate.hql.internal.ast.tree.EntityJoinFromElement) Iterator(java.util.Iterator) JoinProcessor(org.hibernate.hql.internal.ast.util.JoinProcessor)

Example 4 with QueryNode

use of org.hibernate.hql.internal.ast.tree.QueryNode in project hibernate-orm by hibernate.

the class HQLTest method assertInExist.

private void assertInExist(String message, boolean expected, QueryTranslatorImpl translator) {
    AST ast = translator.getSqlAST().getWalker().getAST();
    QueryNode queryNode = (QueryNode) ast;
    AST whereNode = ASTUtil.findTypeInChildren(queryNode, HqlTokenTypes.WHERE);
    AST inNode = whereNode.getFirstChild();
    assertEquals(message, expected, inNode != null && inNode.getType() == HqlTokenTypes.IN);
}
Also used : AST(antlr.collections.AST) QueryNode(org.hibernate.hql.internal.ast.tree.QueryNode)

Example 5 with QueryNode

use of org.hibernate.hql.internal.ast.tree.QueryNode in project hibernate-orm by hibernate.

the class QueryLoader method applyLocks.

@Override
protected String applyLocks(String sql, QueryParameters parameters, Dialect dialect, List<AfterLoadAction> afterLoadActions) throws QueryException {
    // can't cache this stuff either (per-invocation)
    // we are given a map of user-alias -> lock mode
    // create a new map of sql-alias -> lock mode
    final LockOptions lockOptions = parameters.getLockOptions();
    if (lockOptions == null || (lockOptions.getLockMode() == LockMode.NONE && lockOptions.getAliasLockCount() == 0)) {
        return sql;
    }
    // 		some dialects wont allow locking with paging...
    if (shouldUseFollowOnLocking(parameters, dialect, afterLoadActions)) {
        return sql;
    }
    //		there are other conditions we might want to add here, such as checking the result types etc
    //		but those are better served afterQuery we have redone the SQL generation to use ASTs.
    // we need both the set of locks and the columns to reference in locks
    // as the ultimate output of this section...
    final LockOptions locks = new LockOptions(lockOptions.getLockMode());
    final Map<String, String[]> keyColumnNames = dialect.forUpdateOfColumns() ? new HashMap<>() : null;
    locks.setScope(lockOptions.getScope());
    locks.setTimeOut(lockOptions.getTimeOut());
    for (Map.Entry<String, String> entry : sqlAliasByEntityAlias.entrySet()) {
        final String userAlias = entry.getKey();
        final String drivingSqlAlias = entry.getValue();
        if (drivingSqlAlias == null) {
            throw new IllegalArgumentException("could not locate alias to apply lock mode : " + userAlias);
        }
        // at this point we have (drivingSqlAlias) the SQL alias of the driving table
        // corresponding to the given user alias.  However, the driving table is not
        // (necessarily) the table against which we want to apply locks.  Mainly,
        // the exception case here is joined-subclass hierarchies where we instead
        // want to apply the lock against the root table (for all other strategies,
        // it just happens that driving and root are the same).
        final QueryNode select = (QueryNode) queryTranslator.getSqlAST();
        final Lockable drivingPersister = (Lockable) select.getFromClause().findFromElementByUserOrSqlAlias(userAlias, drivingSqlAlias).getQueryable();
        final String sqlAlias = drivingPersister.getRootTableAlias(drivingSqlAlias);
        final LockMode effectiveLockMode = lockOptions.getEffectiveLockMode(userAlias);
        locks.setAliasSpecificLockMode(sqlAlias, effectiveLockMode);
        if (keyColumnNames != null) {
            keyColumnNames.put(sqlAlias, drivingPersister.getRootTableIdentifierColumnNames());
        }
    }
    // apply the collected locks and columns
    return dialect.applyLocksToSql(sql, locks, keyColumnNames);
}
Also used : LockOptions(org.hibernate.LockOptions) QueryNode(org.hibernate.hql.internal.ast.tree.QueryNode) Lockable(org.hibernate.persister.entity.Lockable) LockMode(org.hibernate.LockMode) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

QueryNode (org.hibernate.hql.internal.ast.tree.QueryNode)5 AST (antlr.collections.AST)2 ArrayList (java.util.ArrayList)2 List (java.util.List)2 FromElement (org.hibernate.hql.internal.ast.tree.FromElement)2 HashMap (java.util.HashMap)1 Iterator (java.util.Iterator)1 Map (java.util.Map)1 HibernateException (org.hibernate.HibernateException)1 LockMode (org.hibernate.LockMode)1 LockOptions (org.hibernate.LockOptions)1 EntityGraphQueryHint (org.hibernate.engine.query.spi.EntityGraphQueryHint)1 QueryParameters (org.hibernate.engine.spi.QueryParameters)1 RowSelection (org.hibernate.engine.spi.RowSelection)1 EntityJoinFromElement (org.hibernate.hql.internal.ast.tree.EntityJoinFromElement)1 JoinProcessor (org.hibernate.hql.internal.ast.util.JoinProcessor)1 IdentitySet (org.hibernate.internal.util.collections.IdentitySet)1 Lockable (org.hibernate.persister.entity.Lockable)1