CollectionFetch fetch,
ReaderCollector readerCollector,
FetchStatsImpl fetchStats) {
fetchStats.processingFetch( fetch );
final CollectionReferenceAliases aliases = aliasResolutionContext.resolveCollectionReferenceAliases( fetch.getQuerySpaceUid() );
final QueryableCollection queryableCollection = (QueryableCollection) fetch.getCollectionPersister();
final Joinable joinableCollection = (Joinable) fetch.getCollectionPersister();
if ( fetch.getCollectionPersister().isManyToMany() ) {
// todo : better way to access `ownerTableAlias` here.
// when processing the Join part of this we are able to look up the "lhs table alias" because we know
// the 'lhs' QuerySpace.
//
// Good idea to be able resolve a Join by lookup on the rhs and lhs uid? If so, Fetch
// for many-to-many we have 3 table aliases. By way of example, consider a normal m-n: User<->Role
// where User is the FetchOwner and Role (User.roles) is the Fetch. We'd have:
// 1) the owner's table : user
final String ownerTableAlias = aliasResolutionContext.resolveSqlTableAliasFromQuerySpaceUid( fetchSource.getQuerySpaceUid() );
// 2) the m-n table : user_role
final String collectionTableAlias = aliases.getCollectionTableAlias();
// 3) the element table : role
final String elementTableAlias = aliases.getElementTableAlias();
// add select fragments from the collection table ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
selectStatementBuilder.appendSelectClauseFragment(
joinableCollection.selectFragment(
(Joinable) queryableCollection.getElementPersister(),
elementTableAlias,
collectionTableAlias,
aliases.getEntityElementColumnAliases().getSuffix(),
aliases.getCollectionColumnAliases().getSuffix(),
true
)
);
// add select fragments from the element entity table ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
final OuterJoinLoadable elementPersister = (OuterJoinLoadable) queryableCollection.getElementPersister();
selectStatementBuilder.appendSelectClauseFragment(
elementPersister.selectFragment(
elementTableAlias,
aliases.getEntityElementColumnAliases().getSuffix()
)
);
// add SQL ORDER-BY fragments
final String manyToManyOrdering = queryableCollection.getManyToManyOrderByString( collectionTableAlias );
if ( StringHelper.isNotEmpty( manyToManyOrdering ) ) {
selectStatementBuilder.appendOrderByFragment( manyToManyOrdering );
}
final String ordering = queryableCollection.getSQLOrderByString( collectionTableAlias );
if ( StringHelper.isNotEmpty( ordering ) ) {
selectStatementBuilder.appendOrderByFragment( ordering );
}
// add an EntityReferenceInitializer for the collection elements (keys also?)
final EntityReferenceAliases entityReferenceAliases = new EntityReferenceAliases() {
@Override
public String getTableAlias() {
return aliases.getCollectionTableAlias();
}
@Override
public EntityAliases getColumnAliases() {
return aliases.getEntityElementColumnAliases();
}
};
aliasResolutionContext.registerQuerySpaceAliases( fetch.getQuerySpaceUid(), entityReferenceAliases );
readerCollector.add(
new EntityReferenceInitializerImpl(
(EntityReference) fetch.getElementGraph(),
entityReferenceAliases
)
);
}
else {
final String rhsTableAlias = aliases.getElementTableAlias();
// select the "collection columns"
selectStatementBuilder.appendSelectClauseFragment(
queryableCollection.selectFragment(
rhsTableAlias,
aliases.getCollectionColumnAliases().getSuffix()
)
);
if ( fetch.getCollectionPersister().isOneToMany() ) {
// if the collection elements are entities, select the entity columns as well
final OuterJoinLoadable elementPersister = (OuterJoinLoadable) queryableCollection.getElementPersister();
selectStatementBuilder.appendSelectClauseFragment(
elementPersister.selectFragment(
aliases.getElementTableAlias(),
aliases.getEntityElementColumnAliases().getSuffix()
)
);
final EntityReferenceAliases entityReferenceAliases = new EntityReferenceAliases() {
@Override
public String getTableAlias() {
return aliases.getElementTableAlias();
}
@Override
public EntityAliases getColumnAliases() {
return aliases.getEntityElementColumnAliases();
}
};
aliasResolutionContext.registerQuerySpaceAliases( fetch.getQuerySpaceUid(), entityReferenceAliases );
readerCollector.add(
new EntityReferenceInitializerImpl(