Skip to content

Commit

Permalink
Lazy construct expression context for memory provider feature sources
Browse files Browse the repository at this point in the history
It's not free to calculate, and is only used when
iterating over a memory layer with a subset string set

Results in a big speed up to scripts which fire off many individual
feature requests to a memory provider layer
  • Loading branch information
nyalldawson committed Oct 12, 2020
1 parent 5c8013d commit 1d2bb41
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 10 deletions.
30 changes: 21 additions & 9 deletions src/core/providers/memory/qgsmemoryfeatureiterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ QgsMemoryFeatureIterator::QgsMemoryFeatureIterator( QgsMemoryFeatureSource *sour
if ( !mSource->mSubsetString.isEmpty() )
{
mSubsetExpression = qgis::make_unique< QgsExpression >( mSource->mSubsetString );
mSubsetExpression->prepare( &mSource->mExpressionContext );
mSubsetExpression->prepare( mSource->expressionContext() );
}

if ( !mFilterRect.isNull() && mRequest.flags() & QgsFeatureRequest::ExactIntersect )
Expand All @@ -63,7 +63,7 @@ QgsMemoryFeatureIterator::QgsMemoryFeatureIterator( QgsMemoryFeatureSource *sour
{
mUsingFeatureIdList = true;
mFeatureIdList = mSource->mSpatialIndex->intersects( mFilterRect );
QgsDebugMsg( "Features returned by spatial index: " + QString::number( mFeatureIdList.count() ) );
QgsDebugMsgLevel( "Features returned by spatial index: " + QString::number( mFeatureIdList.count() ), 2 );
}
else if ( mRequest.filterType() == QgsFeatureRequest::FilterFid )
{
Expand Down Expand Up @@ -138,8 +138,8 @@ bool QgsMemoryFeatureIterator::nextFeatureUsingList( QgsFeature &feature )

if ( hasFeature && mSubsetExpression )
{
mSource->mExpressionContext.setFeature( candidate );
if ( !mSubsetExpression->evaluate( &mSource->mExpressionContext ).toBool() )
mSource->expressionContext()->setFeature( candidate );
if ( !mSubsetExpression->evaluate( mSource->expressionContext() ).toBool() )
hasFeature = false;
}

Expand Down Expand Up @@ -198,8 +198,8 @@ bool QgsMemoryFeatureIterator::nextFeatureTraverseAll( QgsFeature &feature )

if ( mSubsetExpression )
{
mSource->mExpressionContext.setFeature( *mSelectIterator );
if ( !mSubsetExpression->evaluate( &mSource->mExpressionContext ).toBool() )
mSource->expressionContext()->setFeature( *mSelectIterator );
if ( !mSubsetExpression->evaluate( mSource->expressionContext() ).toBool() )
hasFeature = false;
}

Expand Down Expand Up @@ -257,14 +257,26 @@ QgsMemoryFeatureSource::QgsMemoryFeatureSource( const QgsMemoryProvider *p )
, mSubsetString( p->mSubsetString )
, mCrs( p->mCrs )
{
mExpressionContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() );
mExpressionContext.setFields( mFields );
}

QgsFeatureIterator QgsMemoryFeatureSource::getFeatures( const QgsFeatureRequest &request )
{
return QgsFeatureIterator( new QgsMemoryFeatureIterator( this, false, request ) );
}

QgsExpressionContext *QgsMemoryFeatureSource::expressionContext()
{
// lazy construct expression context -- it's not free to calculate, and is only used when
// iterating over a memory layer with a subset string set
if ( !mExpressionContext )
{
mExpressionContext = qgis::make_unique< QgsExpressionContext >(
QList<QgsExpressionContextScope *>()
<< QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() ) );
mExpressionContext->setFields( mFields );
}
return mExpressionContext.get();
}

///@endcond PRIVATE
4 changes: 3 additions & 1 deletion src/core/providers/memory/qgsmemoryfeatureiterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@ class QgsMemoryFeatureSource final: public QgsAbstractFeatureSource

QgsFeatureIterator getFeatures( const QgsFeatureRequest &request ) override;

QgsExpressionContext *expressionContext();

private:
QgsFields mFields;
QgsFeatureMap mFeatures;
std::unique_ptr< QgsSpatialIndex > mSpatialIndex;
QString mSubsetString;
QgsExpressionContext mExpressionContext;
std::unique_ptr< QgsExpressionContext > mExpressionContext;
QgsCoordinateReferenceSystem mCrs;

friend class QgsMemoryFeatureIterator;
Expand Down

0 comments on commit 1d2bb41

Please sign in to comment.