Skip to content
Permalink
Browse files

Implement method for caching values within expression contexts

Can be used to store the results of expensive sub-expression
calculations (eg layer aggregates), so that future expression
evaluation using the same context does not have to recalculate
the cached values.
  • Loading branch information
nyalldawson committed May 16, 2016
1 parent 821134c commit 84fc3c3b3dfd306583a217d5581ed1763d0bac6a
@@ -396,6 +396,46 @@ class QgsExpressionContext
*/
void setOriginalValueVariable( const QVariant& value );

/** Sets a value to cache within the expression context. This can be used to cache the results
* of expensive expression sub-calculations, to speed up future evaluations using the same
* expression context.
* @param key unique key for retrieving cached value
* @param value value to cache
* @see hasCachedValue()
* @see cachedValue()
* @see clearCachedValues()
* @note added in QGIS 2.16
*/
void setCachedValue( const QString& key, const QVariant& value ) const;

/** Returns true if the expression context contains a cached value with a matching key.
* @param key unique key used to store cached value
* @see setCachedValue()
* @see cachedValue()
* @see clearCachedValues()
* @note added in QGIS 2.16
*/
bool hasCachedValue( const QString& key ) const;

/** Returns the matching cached value, if set. This can be used to retrieve the previously stored results
* of an expensive expression sub-calculation.
* @param key unique key used to store cached value
* @returns matching cached value, or invalid QVariant if not set
* @see setCachedValue()
* @see hasCachedValue()
* @see clearCachedValues()
* @note added in QGIS 2.16
*/
QVariant cachedValue( const QString& key ) const;

/** Clears all cached values from the context.
* @see setCachedValue()
* @see hasCachedValue()
* @see cachedValue()
* @note added in QGIS 2.16
*/
void clearCachedValues() const;

//! Inbuilt variable name for fields storage
static const QString EXPR_FIELDS;
//! Inbuilt variable name for feature storage
@@ -213,6 +213,7 @@ QgsExpressionContext::QgsExpressionContext( const QgsExpressionContext& other )
mStack << new QgsExpressionContextScope( *scope );
}
mHighlightedVariables = other.mHighlightedVariables;
mCachedValues = other.mCachedValues;
}

QgsExpressionContext& QgsExpressionContext::operator=( const QgsExpressionContext & other )
@@ -224,6 +225,7 @@ QgsExpressionContext& QgsExpressionContext::operator=( const QgsExpressionContex
mStack << new QgsExpressionContextScope( *scope );
}
mHighlightedVariables = other.mHighlightedVariables;
mCachedValues = other.mCachedValues;
return *this;
}

@@ -439,6 +441,26 @@ void QgsExpressionContext::setOriginalValueVariable( const QVariant &value )
value, true ) );
}

void QgsExpressionContext::setCachedValue( const QString& key, const QVariant& value ) const
{
mCachedValues.insert( key, value );
}

bool QgsExpressionContext::hasCachedValue( const QString& key ) const
{
return mCachedValues.contains( key );
}

QVariant QgsExpressionContext::cachedValue( const QString& key ) const
{
return mCachedValues.value( key, QVariant() );
}

void QgsExpressionContext::clearCachedValues() const
{
mCachedValues.clear();
}


//
// QgsExpressionContextUtils
@@ -434,6 +434,46 @@ class CORE_EXPORT QgsExpressionContext
*/
void setOriginalValueVariable( const QVariant& value );

/** Sets a value to cache within the expression context. This can be used to cache the results
* of expensive expression sub-calculations, to speed up future evaluations using the same
* expression context.
* @param key unique key for retrieving cached value
* @param value value to cache
* @see hasCachedValue()
* @see cachedValue()
* @see clearCachedValues()
* @note added in QGIS 2.16
*/
void setCachedValue( const QString& key, const QVariant& value ) const;

/** Returns true if the expression context contains a cached value with a matching key.
* @param key unique key used to store cached value
* @see setCachedValue()
* @see cachedValue()
* @see clearCachedValues()
* @note added in QGIS 2.16
*/
bool hasCachedValue( const QString& key ) const;

/** Returns the matching cached value, if set. This can be used to retrieve the previously stored results
* of an expensive expression sub-calculation.
* @param key unique key used to store cached value
* @returns matching cached value, or invalid QVariant if not set
* @see setCachedValue()
* @see hasCachedValue()
* @see clearCachedValues()
* @note added in QGIS 2.16
*/
QVariant cachedValue( const QString& key ) const;

/** Clears all cached values from the context.
* @see setCachedValue()
* @see hasCachedValue()
* @see cachedValue()
* @note added in QGIS 2.16
*/
void clearCachedValues() const;

//! Inbuilt variable name for fields storage
static const QString EXPR_FIELDS;
//! Inbuilt variable name for feature storage
@@ -458,6 +498,9 @@ class CORE_EXPORT QgsExpressionContext
QList< QgsExpressionContextScope* > mStack;
QStringList mHighlightedVariables;

// Cache is mutable because we want to be able to add cached values to const contexts
mutable QMap< QString, QVariant > mCachedValues;

};

/** \ingroup core
@@ -48,6 +48,8 @@ class TestQgsExpressionContext : public QObject
void layerScope();
void featureBasedContext();

void cache();

private:

class GetTestValueFunction : public QgsScopedExpressionFunction
@@ -641,5 +643,37 @@ void TestQgsExpressionContext::featureBasedContext()
QCOMPARE( evalFields, fields );
}

void TestQgsExpressionContext::cache()
{
//test setting and retrieving cached values
QgsExpressionContext context;

//use a const reference to ensure that cache is usable from const QgsExpressionContexts
const QgsExpressionContext& c = context;

QVERIFY( !c.hasCachedValue( "test" ) );
QVERIFY( !c.cachedValue( "test" ).isValid() );

c.setCachedValue( "test", "my value" );
QVERIFY( c.hasCachedValue( "test" ) );
QCOMPARE( c.cachedValue( "test" ), QVariant( "my value" ) );

// copy should copy cache
QgsExpressionContext context2( c );
QVERIFY( context2.hasCachedValue( "test" ) );
QCOMPARE( context2.cachedValue( "test" ), QVariant( "my value" ) );

// assignment should copy cache
QgsExpressionContext context3;
context3 = c;
QVERIFY( context3.hasCachedValue( "test" ) );
QCOMPARE( context3.cachedValue( "test" ), QVariant( "my value" ) );

// clear cache
c.clearCachedValues();
QVERIFY( !c.hasCachedValue( "test" ) );
QVERIFY( !c.cachedValue( "test" ).isValid() );
}

QTEST_MAIN( TestQgsExpressionContext )
#include "testqgsexpressioncontext.moc"

0 comments on commit 84fc3c3

Please sign in to comment.
You can’t perform that action at this time.