📄 joinprocessor.java
字号:
// $Id: JoinProcessor.java 10824 2006-11-16 19:32:48Z steve.ebersole@jboss.com $package org.hibernate.hql.ast.util;import java.util.ArrayList;import java.util.Iterator;import java.util.ListIterator;import java.util.Collections;import java.util.List;import org.hibernate.AssertionFailure;import org.hibernate.engine.JoinSequence;import org.hibernate.hql.antlr.SqlTokenTypes;import org.hibernate.hql.ast.QueryTranslatorImpl;import org.hibernate.hql.ast.tree.FromClause;import org.hibernate.hql.ast.tree.FromElement;import org.hibernate.hql.ast.tree.QueryNode;import org.hibernate.hql.ast.tree.DotNode;import org.hibernate.sql.JoinFragment;import org.hibernate.util.StringHelper;import antlr.ASTFactory;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * Performs the post-processing of the join information gathered during semantic analysis. * The join generating classes are complex, this encapsulates some of the JoinSequence-related * code. * * @author Joshua Davis */public class JoinProcessor implements SqlTokenTypes { private static final Logger log = LoggerFactory.getLogger( JoinProcessor.class ); private QueryTranslatorImpl queryTranslatorImpl; private SyntheticAndFactory andFactory; /** * Constructs a new JoinProcessor. * * @param astFactory The factory for AST node creation. * @param queryTranslatorImpl The query translator. */ public JoinProcessor(ASTFactory astFactory, QueryTranslatorImpl queryTranslatorImpl) { this.andFactory = new SyntheticAndFactory( astFactory ); this.queryTranslatorImpl = queryTranslatorImpl; } /** * Translates an AST join type (i.e., the token type) into a JoinFragment.XXX join type. * * @param astJoinType The AST join type (from HqlSqlTokenTypes or SqlTokenTypes) * @return a JoinFragment.XXX join type. * @see JoinFragment * @see SqlTokenTypes */ public static int toHibernateJoinType(int astJoinType) { switch ( astJoinType ) { case LEFT_OUTER: return JoinFragment.LEFT_OUTER_JOIN; case INNER: return JoinFragment.INNER_JOIN; case RIGHT_OUTER: return JoinFragment.RIGHT_OUTER_JOIN; default: throw new AssertionFailure( "undefined join type " + astJoinType ); } } public void processJoins(QueryNode query, boolean inSubquery) { 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 = queryTranslatorImpl.isShallowQuery(); boolean includeSubclasses = fromElement.isIncludeSubclasses(); boolean subQuery = fromClause.isSubQuery(); return includeSubclasses && containsTableAlias && !subQuery && !shallowQuery; } } ); addJoinNodes( query, join, fromElement, inSubquery ); } } private void addJoinNodes(QueryNode query, JoinSequence join, FromElement fromElement, boolean inSubquery) { // Generate FROM and WHERE fragments for the from element. JoinFragment joinFragment = join.toJoinFragment( inSubquery ? Collections.EMPTY_MAP : queryTranslatorImpl.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 ); if ( log.isDebugEnabled() ) { log.debug( "Using FROM fragment [" + fromFragment + "]" ); } fromElement.setText( fromFragment.trim() ); // Set the text of the fromElement. } andFactory.addWhereFragment( joinFragment, whereFrag, query, fromElement ); } private String processFromFragment(String frag, JoinSequence join) { String fromFragment = frag.trim(); // The FROM fragment will probably begin with ', '. Remove this if it is present. if ( fromFragment.startsWith( ", " ) ) { fromFragment = fromFragment.substring( 2 ); } return fromFragment; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -