use of org.hibernate.sql.QueryJoinFragment in project hibernate-orm by hibernate.
the class JoinSequence method toJoinFragment.
public JoinFragment toJoinFragment(Map enabledFilters, boolean includeAllSubclassJoins, boolean renderSubclassJoins, String withClauseFragment) throws MappingException {
final QueryJoinFragment joinFragment = new QueryJoinFragment(factory.getDialect(), useThetaStyle);
Iterator<Join> iter;
Join first;
Joinable last;
if (rootJoinable != null) {
joinFragment.addCrossJoin(rootJoinable.getTableName(), rootAlias);
final String filterCondition = rootJoinable.filterFragment(rootAlias, enabledFilters, treatAsDeclarations);
// JoinProcessor needs to know if the where clause fragment came from a dynamic filter or not so it
// can put the where clause fragment in the right place in the SQL AST. 'hasFilterCondition' keeps track
// of that fact.
joinFragment.setHasFilterCondition(joinFragment.addCondition(filterCondition));
addSubclassJoins(joinFragment, rootAlias, rootJoinable, true, includeAllSubclassJoins, treatAsDeclarations);
last = rootJoinable;
} else if (needsTableGroupJoin(joins, withClauseFragment)) {
iter = joins.iterator();
first = iter.next();
final String joinString;
switch(first.joinType) {
case INNER_JOIN:
joinString = " inner join ";
break;
case LEFT_OUTER_JOIN:
joinString = " left outer join ";
break;
case RIGHT_OUTER_JOIN:
joinString = " right outer join ";
break;
case FULL_JOIN:
joinString = " full outer join ";
break;
default:
throw new AssertionFailure("undefined join type");
}
joinFragment.addFromFragmentString(joinString);
joinFragment.addFromFragmentString(" (");
joinFragment.addFromFragmentString(first.joinable.getTableName());
joinFragment.addFromFragmentString(" ");
joinFragment.addFromFragmentString(first.getAlias());
for (Join join : joins) {
// Skip joining the first join node as it is contained in the subquery
if (join != first) {
joinFragment.addJoin(join.getJoinable().getTableName(), join.getAlias(), join.getLHSColumns(), JoinHelper.getRHSColumnNames(join.getAssociationType(), factory), join.joinType, "");
}
addSubclassJoins(joinFragment, join.getAlias(), join.getJoinable(), // TODO: Think about if this could be made always true
join.joinType == JoinType.INNER_JOIN, includeAllSubclassJoins, // builds the JoinSequence for HQL joins
treatAsDeclarations);
}
joinFragment.addFromFragmentString(")");
joinFragment.addFromFragmentString(" on ");
final String rhsAlias = first.getAlias();
final String[] lhsColumns = first.getLHSColumns();
final String[] rhsColumns = JoinHelper.getRHSColumnNames(first.getAssociationType(), factory);
for (int j = 0; j < lhsColumns.length; j++) {
joinFragment.addFromFragmentString(lhsColumns[j]);
joinFragment.addFromFragmentString("=");
joinFragment.addFromFragmentString(rhsAlias);
joinFragment.addFromFragmentString(".");
joinFragment.addFromFragmentString(rhsColumns[j]);
if (j < lhsColumns.length - 1) {
joinFragment.addFromFragmentString(" and ");
}
}
joinFragment.addFromFragmentString(" and ");
joinFragment.addFromFragmentString(withClauseFragment);
return joinFragment;
} else {
last = null;
}
for (Join join : joins) {
// technically the treatAsDeclarations should only apply to rootJoinable or to a single Join,
// but that is not possible atm given how these JoinSequence and Join objects are built.
// However, it is generally ok given how the HQL parser builds these JoinSequences (a HQL join
// results in a JoinSequence with an empty rootJoinable and a single Join). So we use that here
// as an assumption
final String on = join.getAssociationType().getOnCondition(join.getAlias(), factory, enabledFilters, treatAsDeclarations);
String condition;
if (last != null && isManyToManyRoot(last) && ((QueryableCollection) last).getElementType() == join.getAssociationType()) {
// the current join represents the join between a many-to-many association table
// and its "target" table. Here we need to apply any additional filters
// defined specifically on the many-to-many
final String manyToManyFilter = ((QueryableCollection) last).getManyToManyFilterFragment(join.getAlias(), enabledFilters);
condition = "".equals(manyToManyFilter) ? on : "".equals(on) ? manyToManyFilter : on + " and " + manyToManyFilter;
} else {
condition = on;
}
if (withClauseFragment != null && !isManyToManyRoot(join.joinable)) {
condition += " and " + withClauseFragment;
}
joinFragment.addJoin(join.getJoinable().getTableName(), join.getAlias(), join.getLHSColumns(), JoinHelper.getRHSColumnNames(join.getAssociationType(), factory), join.joinType, condition);
if (renderSubclassJoins) {
addSubclassJoins(joinFragment, join.getAlias(), join.getJoinable(), join.joinType == JoinType.INNER_JOIN, includeAllSubclassJoins, // builds the JoinSequence for HQL joins
treatAsDeclarations);
}
last = join.getJoinable();
}
if (next != null) {
joinFragment.addFragment(next.toJoinFragment(enabledFilters, includeAllSubclassJoins));
}
joinFragment.addCondition(conditions.toString());
if (isFromPart) {
joinFragment.clearWherePart();
}
return joinFragment;
}
Aggregations