QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayerFeatureSource* source, bool ownSource, const QgsFeatureRequest& request ) : QgsAbstractFeatureIteratorFromSource<QgsVectorLayerFeatureSource>( source, ownSource, request ) , mFetchedFid( false ) , mInterruptionChecker( nullptr ) { if ( mRequest.filterType() == QgsFeatureRequest::FilterExpression ) { mRequest.expressionContext()->setFields( mSource->mFields ); mRequest.filterExpression()->prepare( mRequest.expressionContext() ); if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { //ensure that all fields required for filter expressions are prepared QSet<int> attributeIndexes = mRequest.filterExpression()->referencedAttributeIndexes( mSource->mFields ); attributeIndexes += mRequest.subsetOfAttributes().toSet(); mRequest.setSubsetOfAttributes( attributeIndexes.toList() ); } } prepareFields(); mHasVirtualAttributes = !mFetchJoinInfo.isEmpty() || !mExpressionFieldInfo.isEmpty(); // by default provider's request is the same mProviderRequest = mRequest; if ( mProviderRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { // prepare list of attributes to match provider fields QSet<int> providerSubset; QgsAttributeList subset = mProviderRequest.subsetOfAttributes(); int nPendingFields = mSource->mFields.count(); Q_FOREACH ( int attrIndex, subset ) { if ( attrIndex < 0 || attrIndex >= nPendingFields ) continue; if ( mSource->mFields.fieldOrigin( attrIndex ) == QgsFields::OriginProvider ) providerSubset << mSource->mFields.fieldOriginIndex( attrIndex ); } // This is done in order to be prepared to do fallback order bys // and be sure we have the required columns. // TODO: // It would be nicer to first check if we can compile the order by // and only modify the subset if we cannot. if ( !mProviderRequest.orderBy().isEmpty() ) { Q_FOREACH ( const QString& attr, mProviderRequest.orderBy().usedAttributes() ) { providerSubset << mSource->mFields.lookupField( attr ); } }
QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayerFeatureSource *source, bool ownSource, const QgsFeatureRequest &request ) : QgsAbstractFeatureIteratorFromSource<QgsVectorLayerFeatureSource>( source, ownSource, request ) , mFetchedFid( false ) { if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mSource->mCrs ) { mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs(), mRequest.transformContext() ); } try { mFilterRect = filterRectToSourceCrs( mTransform ); } catch ( QgsCsException & ) { // can't reproject mFilterRect close(); return; } if ( !mFilterRect.isNull() ) { // update request to be the unprojected filter rect mRequest.setFilterRect( mFilterRect ); } if ( mRequest.filterType() == QgsFeatureRequest::FilterExpression ) { mRequest.expressionContext()->setFields( mSource->mFields ); mRequest.filterExpression()->prepare( mRequest.expressionContext() ); if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { //ensure that all fields required for filter expressions are prepared QSet<int> attributeIndexes = mRequest.filterExpression()->referencedAttributeIndexes( mSource->mFields ); attributeIndexes += mRequest.subsetOfAttributes().toSet(); mRequest.setSubsetOfAttributes( attributeIndexes.toList() ); } } prepareFields(); mHasVirtualAttributes = !mFetchJoinInfo.isEmpty() || !mExpressionFieldInfo.isEmpty(); // by default provider's request is the same mProviderRequest = mRequest; // but we remove any destination CRS parameter - that is handled in QgsVectorLayerFeatureIterator, // not at the provider level. Otherwise virtual fields depending on geometry would have incorrect // values if ( mRequest.destinationCrs().isValid() ) { mProviderRequest.setDestinationCrs( QgsCoordinateReferenceSystem(), mRequest.transformContext() ); } if ( mProviderRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { // prepare list of attributes to match provider fields QSet<int> providerSubset; QgsAttributeList subset = mProviderRequest.subsetOfAttributes(); int nPendingFields = mSource->mFields.count(); Q_FOREACH ( int attrIndex, subset ) { if ( attrIndex < 0 || attrIndex >= nPendingFields ) continue; if ( mSource->mFields.fieldOrigin( attrIndex ) == QgsFields::OriginProvider ) providerSubset << mSource->mFields.fieldOriginIndex( attrIndex ); } // This is done in order to be prepared to do fallback order bys // and be sure we have the required columns. // TODO: // It would be nicer to first check if we can compile the order by // and only modify the subset if we cannot. if ( !mProviderRequest.orderBy().isEmpty() ) { Q_FOREACH ( const QString &attr, mProviderRequest.orderBy().usedAttributes() ) { providerSubset << mSource->mFields.lookupField( attr ); } }