11using System ;
22using System . Collections . Generic ;
33using System . Linq ;
4+ using NHibernate . Persister . Collection ;
45using NHibernate . Persister . Entity ;
56using NHibernate . SqlCommand ;
67
@@ -38,7 +39,7 @@ internal static bool ProcessAsTableGroupJoin(IReadOnlyList<IJoin> tableGroupJoin
3839 join . Joinable . TableName ,
3940 join . Alias ,
4041 join . LHSColumns ,
41- JoinHelper . GetRHSColumnNames ( join . AssociationType , sessionFactoryImplementor ) ,
42+ join . RHSColumns ,
4243 join . JoinType ,
4344 SqlString . Empty ) ;
4445
@@ -51,32 +52,37 @@ internal static bool ProcessAsTableGroupJoin(IReadOnlyList<IJoin> tableGroupJoin
5152 join . Joinable . WhereJoinFragment ( join . Alias , innerJoin , include ) ) ;
5253 }
5354
54- var withClause = GetTableGroupJoinWithClause ( withClauseFragments , first , sessionFactoryImplementor ) ;
55+ var withClause = GetTableGroupJoinWithClause ( withClauseFragments , first ) ;
5556 joinFragment . AddFromFragmentString ( withClause ) ;
5657 return true ;
5758 }
5859
60+ // detect cases when withClause is used on multiple tables or when join keys depend on subclass columns
5961 private static bool NeedsTableGroupJoin ( IReadOnlyList < IJoin > joins , SqlString [ ] withClauseFragments , bool includeSubclasses )
6062 {
61- // If we don't have a with clause, we don't need a table group join
62- if ( withClauseFragments . All ( x => SqlStringHelper . IsEmpty ( x ) ) )
63- {
64- return false ;
65- }
63+ bool hasWithClause = withClauseFragments . Any ( x => SqlStringHelper . IsNotEmpty ( x ) ) ;
6664
67- // If we only have one join, a table group join is only necessary if subclass columns are used in the with clause
68- if ( joins . Count == 1 )
65+ //NH Specific: No alias processing (see hibernate JoinSequence.NeedsTableGroupJoin)
66+ if ( joins . Count > 1 && hasWithClause )
67+ return true ;
68+
69+ foreach ( var join in joins )
6970 {
70- return joins [ 0 ] . Joinable is AbstractEntityPersister persister && persister . HasSubclassJoins ( includeSubclasses ) ;
71- //NH Specific: No alias processing
72- //return isSubclassAliasDereferenced( joins[ 0], withClauseFragment );
71+ var entityPersister = GetEntityPersister ( join . Joinable ) ;
72+ if ( entityPersister ? . HasSubclassJoins ( includeSubclasses ) != true )
73+ continue ;
74+
75+ if ( hasWithClause )
76+ return true ;
77+
78+ if ( entityPersister . ColumnsDependOnSubclassJoins ( join . RHSColumns ) )
79+ return true ;
7380 }
7481
75- //NH Specific: No alias processing (see hibernate JoinSequence.NeedsTableGroupJoin)
76- return true ;
82+ return false ;
7783 }
7884
79- private static SqlString GetTableGroupJoinWithClause ( SqlString [ ] withClauseFragments , IJoin first , ISessionFactoryImplementor factory )
85+ private static SqlString GetTableGroupJoinWithClause ( SqlString [ ] withClauseFragments , IJoin first )
8086 {
8187 SqlStringBuilder fromFragment = new SqlStringBuilder ( ) ;
8288 fromFragment . Add ( ")" ) . Add ( " on " ) ;
@@ -85,12 +91,18 @@ private static SqlString GetTableGroupJoinWithClause(SqlString[] withClauseFragm
8591 var isAssociationJoin = lhsColumns . Length > 0 ;
8692 if ( isAssociationJoin )
8793 {
94+ var entityPersister = GetEntityPersister ( first . Joinable ) ;
8895 string rhsAlias = first . Alias ;
89- string [ ] rhsColumns = JoinHelper . GetRHSColumnNames ( first . AssociationType , factory ) ;
90- fromFragment . Add ( lhsColumns [ 0 ] ) . Add ( "=" ) . Add ( rhsAlias ) . Add ( "." ) . Add ( rhsColumns [ 0 ] ) ;
91- for ( int j = 1 ; j < lhsColumns . Length ; j ++ )
96+ string [ ] rhsColumns = first . RHSColumns ;
97+ for ( int j = 0 ; j < lhsColumns . Length ; j ++ )
9298 {
93- fromFragment . Add ( " and " ) . Add ( lhsColumns [ j ] ) . Add ( "=" ) . Add ( rhsAlias ) . Add ( "." ) . Add ( rhsColumns [ j ] ) ;
99+ fromFragment . Add ( lhsColumns [ j ] )
100+ . Add ( "=" )
101+ . Add ( entityPersister ? . GenerateTableAliasForColumn ( rhsAlias , rhsColumns [ j ] ) ?? rhsAlias )
102+ . Add ( "." )
103+ . Add ( rhsColumns [ j ] ) ;
104+ if ( j != lhsColumns . Length - 1 )
105+ fromFragment . Add ( " and " ) ;
94106 }
95107 }
96108
@@ -99,6 +111,15 @@ private static SqlString GetTableGroupJoinWithClause(SqlString[] withClauseFragm
99111 return fromFragment . ToSqlString ( ) ;
100112 }
101113
114+ private static AbstractEntityPersister GetEntityPersister ( IJoinable joinable )
115+ {
116+ if ( ! joinable . IsCollection )
117+ return joinable as AbstractEntityPersister ;
118+
119+ var collection = ( IQueryableCollection ) joinable ;
120+ return collection . ElementType . IsEntityType ? collection . ElementPersister as AbstractEntityPersister : null ;
121+ }
122+
102123 private static void AppendWithClause ( SqlStringBuilder fromFragment , bool hasConditions , SqlString [ ] withClauseFragments )
103124 {
104125 for ( var i = 0 ; i < withClauseFragments . Length ; i ++ )
0 commit comments