@@ -559,6 +559,7 @@ void QgsVectorLayerFeatureIterator::prepareFields()
559
559
mPreparedFields .clear ();
560
560
mFieldsToPrepare .clear ();
561
561
mFetchJoinInfo .clear ();
562
+ mOrderedJoinInfoList .clear ();
562
563
563
564
mExpressionContext .reset ( new QgsExpressionContext () );
564
565
mExpressionContext ->appendScope ( QgsExpressionContextUtils::globalScope () );
@@ -576,6 +577,70 @@ void QgsVectorLayerFeatureIterator::prepareFields()
576
577
mPreparedFields << fieldIdx;
577
578
prepareField ( fieldIdx );
578
579
}
580
+
581
+ // sort joins by dependency
582
+ if ( mFetchJoinInfo .size () > 0 )
583
+ {
584
+ createOrderedJoinList ();
585
+ }
586
+ }
587
+
588
+ void QgsVectorLayerFeatureIterator::createOrderedJoinList ()
589
+ {
590
+ mOrderedJoinInfoList = mFetchJoinInfo .values ();
591
+ if ( mOrderedJoinInfoList .size () < 2 )
592
+ {
593
+ return ;
594
+ }
595
+
596
+ QSet<int > resolvedFields; // todo: get provider / virtual fields without joins
597
+
598
+ // add all provider fields without joins as resolved fields
599
+ QList< int >::const_iterator prepFieldIt = mPreparedFields .constBegin ();
600
+ for ( ; prepFieldIt != mPreparedFields .constEnd (); ++prepFieldIt )
601
+ {
602
+ if ( mSource ->mFields .fieldOrigin ( *prepFieldIt ) != QgsFields::OriginJoin )
603
+ {
604
+ resolvedFields.insert ( *prepFieldIt );
605
+ }
606
+ }
607
+
608
+ // iterate through the joins. If target field is not yet covered, move the entry to the end of the list
609
+
610
+ // some join combinations might not have a resolution at all
611
+ int maxIterations = ( mOrderedJoinInfoList .size () + 1 ) * mOrderedJoinInfoList .size () / 2.0 ;
612
+ int currentIteration = 0 ;
613
+
614
+ for ( int i = 0 ; i < mOrderedJoinInfoList .size () - 1 ; ++i )
615
+ {
616
+ if ( !resolvedFields.contains ( mOrderedJoinInfoList .at ( i ).targetField ) )
617
+ {
618
+ mOrderedJoinInfoList .append ( mOrderedJoinInfoList .at ( i ) );
619
+ mOrderedJoinInfoList .removeAt ( i );
620
+ --i;
621
+ }
622
+ else
623
+ {
624
+ int offset = mOrderedJoinInfoList .at ( i ).indexOffset ;
625
+ int joinField = mOrderedJoinInfoList .at ( i ).joinField ;
626
+
627
+ QgsAttributeList attributes = mOrderedJoinInfoList .at ( i ).attributes ;
628
+ QgsAttributeList::const_iterator attIt = attributes.constBegin ();
629
+ for ( ; attIt != attributes.constEnd (); ++attIt )
630
+ {
631
+ if ( *attIt != joinField )
632
+ {
633
+ resolvedFields.insert ( joinField < *attIt ? *attIt + offset - 1 : *attIt + offset );
634
+ }
635
+ }
636
+ }
637
+
638
+ ++currentIteration;
639
+ if ( currentIteration >= maxIterations )
640
+ {
641
+ break ;
642
+ }
643
+ }
579
644
}
580
645
581
646
void QgsVectorLayerFeatureIterator::prepareField ( int fieldIdx )
@@ -602,21 +667,18 @@ void QgsVectorLayerFeatureIterator::prepareField( int fieldIdx )
602
667
603
668
void QgsVectorLayerFeatureIterator::addJoinedAttributes ( QgsFeature &f )
604
669
{
605
- QMap< const QgsVectorJoinInfo*, FetchJoinInfo>::const_iterator joinIt = mFetchJoinInfo .constBegin ();
606
- for ( ; joinIt != mFetchJoinInfo .constEnd (); ++joinIt )
670
+ QList< FetchJoinInfo >::const_iterator joinIt = mOrderedJoinInfoList .constBegin ();
671
+ for ( ; joinIt != mOrderedJoinInfoList .constEnd (); ++joinIt )
607
672
{
608
- const FetchJoinInfo& info = joinIt.value ();
609
- Q_ASSERT ( joinIt.key () );
610
-
611
- QVariant targetFieldValue = f.attribute ( info.targetField );
673
+ QVariant targetFieldValue = f.attribute ( joinIt->targetField );
612
674
if ( !targetFieldValue.isValid () )
613
675
continue ;
614
676
615
- const QHash< QString, QgsAttributes>& memoryCache = info. joinInfo ->cachedAttributes ;
677
+ const QHash< QString, QgsAttributes>& memoryCache = joinIt-> joinInfo ->cachedAttributes ;
616
678
if ( memoryCache.isEmpty () )
617
- info. addJoinedAttributesDirect ( f, targetFieldValue );
679
+ joinIt-> addJoinedAttributesDirect ( f, targetFieldValue );
618
680
else
619
- info. addJoinedAttributesCached ( f, targetFieldValue );
681
+ joinIt-> addJoinedAttributesCached ( f, targetFieldValue );
620
682
}
621
683
}
622
684
0 commit comments