JoinProcessorpublic class JoinProcessor extends Object implements org.hibernate.hql.antlr.SqlTokenTypesPerforms 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. |
Fields Summary |
---|
private static final Log | log | private org.hibernate.hql.ast.QueryTranslatorImpl | queryTranslatorImpl | private SyntheticAndFactory | andFactory |
Methods Summary |
---|
private void | addJoinNodes(org.hibernate.hql.ast.tree.QueryNode query, org.hibernate.engine.JoinSequence join, org.hibernate.hql.ast.tree.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 java.lang.String | processFromFragment(java.lang.String frag, org.hibernate.engine.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;
| public void | processJoins(org.hibernate.hql.ast.tree.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 );
}
| public static int | toHibernateJoinType(int astJoinType)Translates an AST join type (i.e., the token type) into a JoinFragment.XXX join type.
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 );
}
|
|