@@ -15,6 +15,8 @@ namespace NHibernate.Loader
15
15
public class JoinWalker
16
16
{
17
17
private readonly ISessionFactoryImplementor factory ;
18
+ protected Queue < QueueEntry > joinQueue = new Queue < QueueEntry > ( ) ;
19
+ private int depth ;
18
20
protected readonly IList < OuterJoinableAssociation > associations = new List < OuterJoinableAssociation > ( ) ;
19
21
private readonly HashSet < AssociationKey > visitedAssociationKeys = new HashSet < AssociationKey > ( ) ;
20
22
private readonly IDictionary < string , IFilter > enabledFilters ;
@@ -188,17 +190,28 @@ private void AddAssociationToJoinTree(IAssociationType type, string[] aliasedLhs
188
190
assoc . ValidateJoin ( path ) ;
189
191
AddAssociation ( assoc ) ;
190
192
191
- int nextDepth = currentDepth + 1 ;
192
-
193
- if ( qc == null )
193
+ if ( qc != null )
194
194
{
195
- IOuterJoinLoadable pjl = joinable as IOuterJoinLoadable ;
196
- if ( pjl != null )
197
- WalkEntityTree ( pjl , subalias , path , nextDepth ) ;
195
+ joinQueue . Enqueue (
196
+ new CollectionQueueEntry ( )
197
+ {
198
+ Persister = qc ,
199
+ Alias = subalias ,
200
+ Path = path ,
201
+ PathAlias = pathAlias ,
202
+ }
203
+ ) ;
198
204
}
199
- else
205
+ else if ( joinable is IOuterJoinLoadable jl )
200
206
{
201
- WalkCollectionTree ( qc , subalias , path , pathAlias , nextDepth ) ;
207
+ joinQueue . Enqueue (
208
+ new EntityQueueEntry ( )
209
+ {
210
+ Persister = jl ,
211
+ Alias = subalias ,
212
+ Path = path ,
213
+ }
214
+ ) ;
202
215
}
203
216
}
204
217
@@ -299,16 +312,55 @@ private void AddAssociation(OuterJoinableAssociation association)
299
312
/// </summary>
300
313
protected void WalkEntityTree ( IOuterJoinLoadable persister , string alias )
301
314
{
302
- WalkEntityTree ( persister , alias , string . Empty , 0 ) ;
315
+ joinQueue . Enqueue (
316
+ new EntityQueueEntry ( )
317
+ {
318
+ Persister = persister ,
319
+ Alias = alias ,
320
+ }
321
+ ) ;
322
+
323
+ WalkTree ( ) ;
303
324
}
304
325
305
326
/// <summary>
306
327
/// For a collection role, return a list of associations to be fetched by outerjoin
307
328
/// </summary>
308
329
protected void WalkCollectionTree ( IQueryableCollection persister , string alias )
309
330
{
310
- WalkCollectionTree ( persister , alias , string . Empty , string . Empty , 0 ) ;
311
- //TODO: when this is the entry point, we should use an INNER_JOIN for fetching the many-to-many elements!
331
+ joinQueue . Enqueue (
332
+ new CollectionQueueEntry ( )
333
+ {
334
+ Persister = persister ,
335
+ Alias = alias ,
336
+ }
337
+ ) ;
338
+
339
+ WalkTree ( ) ;
340
+ }
341
+
342
+ protected void WalkTree ( )
343
+ {
344
+ while ( joinQueue . Count > 0 )
345
+ {
346
+ QueueEntry entry = joinQueue . Dequeue ( ) ;
347
+
348
+ switch ( entry )
349
+ {
350
+ case CollectionQueueEntry ce :
351
+ WalkCollectionTree ( ce . Persister , ce . Alias , ce . Path , ce . PathAlias , depth ) ;
352
+ break ;
353
+ case PropertyQueueEntry pe :
354
+ WalkPropertyTree ( pe . Persister , pe . Type , pe . Index , pe . Alias , pe . Path , depth ) ;
355
+ break ;
356
+ case EntityQueueEntry eqe :
357
+ WalkEntityTree ( eqe . Persister , eqe . Alias , eqe . Path , depth ) ;
358
+ break ;
359
+ default :
360
+ depth ++ ;
361
+ break ;
362
+ }
363
+ }
312
364
}
313
365
314
366
/// <summary>
@@ -442,21 +494,42 @@ private void WalkEntityAssociationTree(IAssociationType associationType, IOuterJ
442
494
protected virtual void WalkEntityTree ( IOuterJoinLoadable persister , string alias , string path , int currentDepth )
443
495
{
444
496
int n = persister . CountSubclassProperties ( ) ;
497
+
445
498
for ( int i = 0 ; i < n ; i ++ )
446
499
{
447
500
IType type = persister . GetSubclassPropertyType ( i ) ;
448
- ILhsAssociationTypeSqlInfo associationTypeSQLInfo = JoinHelper . GetLhsSqlInfo ( alias , i , persister , Factory ) ;
449
- if ( type . IsAssociationType )
450
- {
451
- WalkEntityAssociationTree ( ( IAssociationType ) type , persister , i , alias , path ,
452
- persister . IsSubclassPropertyNullable ( i ) , currentDepth , associationTypeSQLInfo ) ;
453
- }
454
- else if ( type . IsComponentType )
501
+
502
+ if ( type . IsAssociationType || type . IsComponentType )
455
503
{
456
- WalkComponentTree ( ( IAbstractComponentType ) type , 0 , alias , SubPath ( path , persister . GetSubclassPropertyName ( i ) ) ,
457
- currentDepth , associationTypeSQLInfo ) ;
504
+ joinQueue . Enqueue (
505
+ new PropertyQueueEntry ( )
506
+ {
507
+ Persister = persister ,
508
+ Alias = alias ,
509
+ Path = path ,
510
+ Index = i ,
511
+ Type = type ,
512
+ }
513
+ ) ;
458
514
}
459
515
}
516
+ joinQueue . Enqueue ( null ) ;
517
+ }
518
+
519
+ protected void WalkPropertyTree ( IOuterJoinLoadable persister , IType type , int index , string alias , string path , int currentDepth )
520
+ {
521
+ ILhsAssociationTypeSqlInfo associationTypeSQLInfo = JoinHelper . GetLhsSqlInfo ( alias , index , persister , Factory ) ;
522
+
523
+ if ( type . IsAssociationType )
524
+ {
525
+ WalkEntityAssociationTree ( ( IAssociationType ) type , persister , index , alias , path ,
526
+ persister . IsSubclassPropertyNullable ( index ) , currentDepth , associationTypeSQLInfo ) ;
527
+ }
528
+ else if ( type . IsComponentType )
529
+ {
530
+ WalkComponentTree ( ( IAbstractComponentType ) type , 0 , alias , SubPath ( path , persister . GetSubclassPropertyName ( index ) ) ,
531
+ currentDepth , associationTypeSQLInfo ) ;
532
+ }
460
533
}
461
534
462
535
/// <summary>
@@ -1201,5 +1274,30 @@ protected static string GetSelectFragment(OuterJoinableAssociation join, string
1201
1274
{
1202
1275
return join . GetSelectFragment ( entitySuffix , collectionSuffix , next ) ;
1203
1276
}
1277
+
1278
+ protected abstract class QueueEntry { }
1279
+
1280
+ protected abstract class QueueEntry < T > : QueueEntry where T : IJoinable
1281
+ {
1282
+ public string Alias { get ; set ; }
1283
+ public T Persister { get ; set ; }
1284
+ }
1285
+
1286
+ protected class EntityQueueEntry < T > : QueueEntry < T > where T : IJoinable
1287
+ {
1288
+ public string Path { get ; set ; }
1289
+ }
1290
+ protected class EntityQueueEntry : EntityQueueEntry < IOuterJoinLoadable > { }
1291
+
1292
+ protected class CollectionQueueEntry : EntityQueueEntry < IQueryableCollection >
1293
+ {
1294
+ public string PathAlias { get ; set ; }
1295
+ }
1296
+
1297
+ protected class PropertyQueueEntry : EntityQueueEntry
1298
+ {
1299
+ public int Index { get ; set ; }
1300
+ public IType Type { get ; set ; }
1301
+ }
1204
1302
}
1205
1303
}
0 commit comments