Skip to content

Commit fe0596f

Browse files
committedNov 20, 2013
Do not keep pointer to vector layer in vector layer feature iterator.
This will make the iterator safe to changes in vector layer while the iterator is still active.
1 parent 2fcf556 commit fe0596f

File tree

2 files changed

+40
-34
lines changed

2 files changed

+40
-34
lines changed
 

‎src/core/qgsvectorlayerfeatureiterator.cpp

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,28 @@
2121
#include "qgsvectorlayerjoinbuffer.h"
2222

2323
QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* layer, const QgsFeatureRequest& request )
24-
: QgsAbstractFeatureIterator( request ), L( layer )
24+
: QgsAbstractFeatureIterator( request )
2525
{
26-
QgsVectorLayerJoinBuffer* joinBuffer = L->mJoinBuffer;
26+
mProvider = layer->dataProvider();
27+
mFields = layer->pendingFields();
28+
mAllAttributesList = layer->pendingAllAttributesList();
29+
mJoinBuffer = new QgsVectorLayerJoinBuffer( *layer->mJoinBuffer );
2730

2831
mChangedFeaturesRequest = mRequest;
2932

30-
if ( L->editBuffer() )
33+
if ( layer->editBuffer() )
3134
{
32-
mAddedFeatures = QgsFeatureMap( L->editBuffer()->addedFeatures() );
33-
mChangedGeometries = QgsGeometryMap( L->editBuffer()->changedGeometries() );
34-
mDeletedFeatureIds = QgsFeatureIds( L->editBuffer()->deletedFeatureIds() );
35-
mChangedAttributeValues = QgsChangedAttributesMap( L->editBuffer()->changedAttributeValues() );
36-
mAddedAttributes = QList<QgsField>( L->editBuffer()->addedAttributes() );
37-
mDeletedAttributeIds = QgsAttributeList( L->editBuffer()->deletedAttributeIds() );
38-
mChangedFeaturesRequest.setFilterFids( L->editBuffer()->changedAttributeValues().keys().toSet() );
35+
mAddedFeatures = QgsFeatureMap( layer->editBuffer()->addedFeatures() );
36+
mChangedGeometries = QgsGeometryMap( layer->editBuffer()->changedGeometries() );
37+
mDeletedFeatureIds = QgsFeatureIds( layer->editBuffer()->deletedFeatureIds() );
38+
mChangedAttributeValues = QgsChangedAttributesMap( layer->editBuffer()->changedAttributeValues() );
39+
mAddedAttributes = QList<QgsField>( layer->editBuffer()->addedAttributes() );
40+
mDeletedAttributeIds = QgsAttributeList( layer->editBuffer()->deletedAttributeIds() );
41+
mChangedFeaturesRequest.setFilterFids( layer->editBuffer()->changedAttributeValues().keys().toSet() );
3942
}
4043

4144
// prepare joins: may add more attributes to fetch (in order to allow join)
42-
if ( joinBuffer->containsJoins() )
45+
if ( mJoinBuffer->containsJoins() )
4346
prepareJoins();
4447

4548
// by default provider's request is the same
@@ -50,14 +53,13 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* la
5053
// prepare list of attributes to match provider fields
5154
QgsAttributeList providerSubset;
5255
QgsAttributeList subset = mProviderRequest.subsetOfAttributes();
53-
const QgsFields &pendingFields = L->pendingFields();
54-
int nPendingFields = pendingFields.count();
56+
int nPendingFields = mFields.count();
5557
for ( int i = 0; i < subset.count(); ++i )
5658
{
5759
int attrIndex = subset[i];
5860
if ( attrIndex < 0 || attrIndex >= nPendingFields ) continue;
59-
if ( L->pendingFields().fieldOrigin( attrIndex ) == QgsFields::OriginProvider )
60-
providerSubset << L->pendingFields().fieldOriginIndex( attrIndex );
61+
if ( mFields.fieldOrigin( attrIndex ) == QgsFields::OriginProvider )
62+
providerSubset << mFields.fieldOriginIndex( attrIndex );
6163
}
6264
mProviderRequest.setSubsetOfAttributes( providerSubset );
6365
}
@@ -68,28 +70,30 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* la
6870
}
6971
else // no filter or filter by rect
7072
{
71-
if ( L->editBuffer() )
73+
if ( layer->editBuffer() )
7274
{
73-
mChangedFeaturesIterator = L->dataProvider()->getFeatures( mChangedFeaturesRequest );
75+
mChangedFeaturesIterator = layer->dataProvider()->getFeatures( mChangedFeaturesRequest );
7476
}
7577
else
7678
{
77-
mProviderIterator = L->dataProvider()->getFeatures( mProviderRequest );
79+
mProviderIterator = layer->dataProvider()->getFeatures( mProviderRequest );
7880
}
7981

8082
rewindEditBuffer();
8183
}
8284

8385
if ( mRequest.filterType() == QgsFeatureRequest::FilterExpression )
8486
{
85-
mRequest.filterExpression()->prepare( L->pendingFields() );
87+
mRequest.filterExpression()->prepare( mFields );
8688
}
8789
}
8890

8991

9092
QgsVectorLayerFeatureIterator::~QgsVectorLayerFeatureIterator()
9193
{
9294
close();
95+
96+
delete mJoinBuffer;
9397
}
9498

9599

@@ -135,7 +139,7 @@ bool QgsVectorLayerFeatureIterator::fetchFeature( QgsFeature& f )
135139
if ( mProviderIterator.isClosed() )
136140
{
137141
mChangedFeaturesIterator.close();
138-
mProviderIterator = L->dataProvider()->getFeatures( mProviderRequest );
142+
mProviderIterator = mProvider->getFeatures( mProviderRequest );
139143
}
140144

141145
while ( mProviderIterator.nextFeature( f ) )
@@ -144,7 +148,7 @@ bool QgsVectorLayerFeatureIterator::fetchFeature( QgsFeature& f )
144148
continue;
145149

146150
// TODO[MD]: just one resize of attributes
147-
f.setFields( &L->mUpdatedFields );
151+
f.setFields( &mFields );
148152

149153
// update attributes
150154
updateChangedAttributes( f );
@@ -227,7 +231,7 @@ void QgsVectorLayerFeatureIterator::useAddedFeature( const QgsFeature& src, QgsF
227231
{
228232
f.setFeatureId( src.id() );
229233
f.setValid( true );
230-
f.setFields( &L->mUpdatedFields );
234+
f.setFields( &mFields );
231235

232236
if ( src.geometry() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) )
233237
f.setGeometry( *src.geometry() );
@@ -298,7 +302,7 @@ void QgsVectorLayerFeatureIterator::useChangedAttributeFeature( QgsFeatureId fid
298302
{
299303
f.setFeatureId( fid );
300304
f.setValid( true );
301-
f.setFields( &L->mUpdatedFields );
305+
f.setFields( &mFields );
302306

303307
if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) )
304308
f.setGeometry( geom );
@@ -315,7 +319,7 @@ void QgsVectorLayerFeatureIterator::useChangedAttributeFeature( QgsFeatureId fid
315319
{
316320
request.setSubsetOfAttributes( mProviderRequest.subsetOfAttributes() );
317321
}
318-
QgsFeatureIterator fi = L->dataProvider()->getFeatures( request );
322+
QgsFeatureIterator fi = mProvider->getFeatures( request );
319323
if ( fi.nextFeature( tmp ) )
320324
{
321325
updateChangedAttributes( tmp );
@@ -341,21 +345,18 @@ void QgsVectorLayerFeatureIterator::rewindEditBuffer()
341345

342346
void QgsVectorLayerFeatureIterator::prepareJoins()
343347
{
344-
QgsAttributeList fetchAttributes = ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) ? mRequest.subsetOfAttributes() : L->pendingAllAttributesList();
348+
QgsAttributeList fetchAttributes = ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) ? mRequest.subsetOfAttributes() : mAllAttributesList;
345349
QgsAttributeList sourceJoinFields; // attributes that also need to be fetched from this layer in order to have joins working
346350

347351
mFetchJoinInfo.clear();
348352

349-
QgsVectorLayerJoinBuffer* joinBuffer = L->mJoinBuffer;
350-
const QgsFields& fields = L->pendingFields();
351-
352353
for ( QgsAttributeList::const_iterator attIt = fetchAttributes.constBegin(); attIt != fetchAttributes.constEnd(); ++attIt )
353354
{
354-
if ( fields.fieldOrigin( *attIt ) != QgsFields::OriginJoin )
355+
if ( mFields.fieldOrigin( *attIt ) != QgsFields::OriginJoin )
355356
continue;
356357

357358
int sourceLayerIndex;
358-
const QgsVectorJoinInfo* joinInfo = joinBuffer->joinForFieldIndex( *attIt, fields, sourceLayerIndex );
359+
const QgsVectorJoinInfo* joinInfo = mJoinBuffer->joinForFieldIndex( *attIt, mFields, sourceLayerIndex );
359360
Q_ASSERT( joinInfo );
360361

361362
QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo->joinLayerId ) );
@@ -370,7 +371,7 @@ void QgsVectorLayerFeatureIterator::prepareJoins()
370371
if ( joinInfo->targetFieldName.isEmpty() )
371372
info.targetField = joinInfo->targetFieldIndex; //for compatibility with 1.x
372373
else
373-
info.targetField = fields.indexFromName( joinInfo->targetFieldName );
374+
info.targetField = mFields.indexFromName( joinInfo->targetFieldName );
374375

375376
if ( joinInfo->joinFieldName.isEmpty() )
376377
info.joinField = joinInfo->joinFieldIndex; //for compatibility with 1.x
@@ -401,7 +402,7 @@ void QgsVectorLayerFeatureIterator::prepareJoins()
401402
void QgsVectorLayerFeatureIterator::addJoinedAttributes( QgsFeature &f )
402403
{
403404
// make sure we have space for newly added attributes
404-
f.attributes().resize( L->pendingFields().count() ); // f.attributes().count() + mJoinedAttributesCount );
405+
f.attributes().resize( mFields.count() ); // f.attributes().count() + mJoinedAttributesCount );
405406

406407
QMap<QgsVectorLayer*, FetchJoinInfo>::const_iterator joinIt = mFetchJoinInfo.constBegin();
407408
for ( ; joinIt != mFetchJoinInfo.constEnd(); ++joinIt )
@@ -545,7 +546,7 @@ bool QgsVectorLayerFeatureIterator::nextFeatureFid( QgsFeature& f )
545546
}
546547

547548
// regular features
548-
QgsFeatureIterator fi = L->dataProvider()->getFeatures( mProviderRequest );
549+
QgsFeatureIterator fi = mProvider->getFeatures( mProviderRequest );
549550
if ( fi.nextFeature( f ) )
550551
{
551552
updateChangedAttributes( f );

‎src/core/qgsvectorlayerfeatureiterator.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ typedef QMap<QgsFeatureId, QgsFeature> QgsFeatureMap;
2424
class QgsVectorLayer;
2525
class QgsVectorLayerEditBuffer;
2626
struct QgsVectorJoinInfo;
27+
class QgsVectorLayerJoinBuffer;
2728

2829
class CORE_EXPORT QgsVectorLayerFeatureIterator : public QgsAbstractFeatureIterator
2930
{
@@ -46,7 +47,11 @@ class CORE_EXPORT QgsVectorLayerFeatureIterator : public QgsAbstractFeatureItera
4647
//! while for others filtering is left to the provider implementation.
4748
inline virtual bool nextFeatureFilterExpression( QgsFeature &f ) { return fetchFeature( f ); }
4849

49-
QgsVectorLayer* L;
50+
QgsVectorDataProvider* mProvider;
51+
QgsFields mFields;
52+
QgsAttributeList mAllAttributesList;
53+
54+
QgsVectorLayerJoinBuffer* mJoinBuffer;
5055

5156
QgsFeatureRequest mProviderRequest;
5257
QgsFeatureIterator mProviderIterator;

0 commit comments

Comments
 (0)
Please sign in to comment.