Skip to content

Commit 0cc7311

Browse files
committed
Collapse static nodes in QgsExpression:prepare()
If the result of a node in a QgsExpression can already be determined to be static at preparation time, there is no need to re-evaluate it for every feature.
1 parent a8fc2c1 commit 0cc7311

File tree

2 files changed

+155
-48
lines changed

2 files changed

+155
-48
lines changed

src/core/qgsexpression.cpp

+100-17
Original file line numberDiff line numberDiff line change
@@ -4708,7 +4708,7 @@ QString QgsExpression::NodeList::dump() const
47084708

47094709
//
47104710

4711-
QVariant QgsExpression::NodeUnaryOperator::eval( QgsExpression *parent, const QgsExpressionContext *context )
4711+
QVariant QgsExpression::NodeUnaryOperator::evalNode( QgsExpression *parent, const QgsExpressionContext *context )
47124712
{
47134713
QVariant val = mOperand->eval( parent, context );
47144714
ENSURE_NO_EVAL_ERROR;
@@ -4735,7 +4735,7 @@ QVariant QgsExpression::NodeUnaryOperator::eval( QgsExpression *parent, const Qg
47354735
return QVariant();
47364736
}
47374737

4738-
bool QgsExpression::NodeUnaryOperator::prepare( QgsExpression *parent, const QgsExpressionContext *context )
4738+
bool QgsExpression::NodeUnaryOperator::prepareNode( QgsExpression *parent, const QgsExpressionContext *context )
47394739
{
47404740
return mOperand->prepare( parent, context );
47414741
}
@@ -4760,9 +4760,14 @@ QgsExpression::Node *QgsExpression::NodeUnaryOperator::clone() const
47604760
return new NodeUnaryOperator( mOp, mOperand->clone() );
47614761
}
47624762

4763+
bool QgsExpression::NodeUnaryOperator::isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const
4764+
{
4765+
return mOperand->isStatic( parent, context );
4766+
}
4767+
47634768
//
47644769

4765-
QVariant QgsExpression::NodeBinaryOperator::eval( QgsExpression *parent, const QgsExpressionContext *context )
4770+
QVariant QgsExpression::NodeBinaryOperator::evalNode( QgsExpression *parent, const QgsExpressionContext *context )
47664771
{
47674772
QVariant vL = mOpLeft->eval( parent, context );
47684773
ENSURE_NO_EVAL_ERROR;
@@ -4945,13 +4950,13 @@ QVariant QgsExpression::NodeBinaryOperator::eval( QgsExpression *parent, const Q
49454950
QgsExpression::NodeLiteral nL( lL.at( i ) );
49464951
QgsExpression::NodeLiteral nR( lR.at( i ) );
49474952
QgsExpression::NodeBinaryOperator eqNode( boEQ, nL.clone(), nR.clone() );
4948-
QVariant eq = eqNode.eval( parent, context );
4953+
QVariant eq = eqNode.evalNode( parent, context );
49494954
ENSURE_NO_EVAL_ERROR;
49504955
if ( eq == TVL_False )
49514956
{
49524957
// return the two items comparison
49534958
QgsExpression::NodeBinaryOperator node( mOp, nL.clone(), nR.clone() );
4954-
QVariant v = node.eval( parent, context );
4959+
QVariant v = node.evalNode( parent, context );
49554960
ENSURE_NO_EVAL_ERROR;
49564961
return v;
49574962
}
@@ -5186,7 +5191,7 @@ double QgsExpression::NodeBinaryOperator::computeDouble( double x, double y )
51865191
}
51875192
}
51885193

5189-
bool QgsExpression::NodeBinaryOperator::prepare( QgsExpression *parent, const QgsExpressionContext *context )
5194+
bool QgsExpression::NodeBinaryOperator::prepareNode( QgsExpression *parent, const QgsExpressionContext *context )
51905195
{
51915196
bool resL = mOpLeft->prepare( parent, context );
51925197
bool resR = mOpRight->prepare( parent, context );
@@ -5326,9 +5331,14 @@ QgsExpression::Node *QgsExpression::NodeBinaryOperator::clone() const
53265331
return new NodeBinaryOperator( mOp, mOpLeft->clone(), mOpRight->clone() );
53275332
}
53285333

5334+
bool QgsExpression::NodeBinaryOperator::isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const
5335+
{
5336+
return mOpLeft->isStatic( parent, context ) && mOpRight->isStatic( parent, context );
5337+
}
5338+
53295339
//
53305340

5331-
QVariant QgsExpression::NodeInOperator::eval( QgsExpression *parent, const QgsExpressionContext *context )
5341+
QVariant QgsExpression::NodeInOperator::evalNode( QgsExpression *parent, const QgsExpressionContext *context )
53325342
{
53335343
if ( mList->count() == 0 )
53345344
return mNotIn ? TVL_True : TVL_False;
@@ -5378,7 +5388,7 @@ QVariant QgsExpression::NodeInOperator::eval( QgsExpression *parent, const QgsEx
53785388
return mNotIn ? TVL_True : TVL_False;
53795389
}
53805390

5381-
bool QgsExpression::NodeInOperator::prepare( QgsExpression *parent, const QgsExpressionContext *context )
5391+
bool QgsExpression::NodeInOperator::prepareNode( QgsExpression *parent, const QgsExpressionContext *context )
53825392
{
53835393
bool res = mNode->prepare( parent, context );
53845394
Q_FOREACH ( Node *n, mList->list() )
@@ -5398,9 +5408,23 @@ QgsExpression::Node *QgsExpression::NodeInOperator::clone() const
53985408
return new NodeInOperator( mNode->clone(), mList->clone(), mNotIn );
53995409
}
54005410

5411+
bool QgsExpression::NodeInOperator::isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const
5412+
{
5413+
if ( !mNode->isStatic( parent, context ) )
5414+
return false;
5415+
5416+
Q_FOREACH ( Node *n, mList->list() )
5417+
{
5418+
if ( !n->isStatic( parent, context ) )
5419+
return false;
5420+
}
5421+
5422+
return true;
5423+
}
5424+
54015425
//
54025426

5403-
QVariant QgsExpression::NodeFunction::eval( QgsExpression *parent, const QgsExpressionContext *context )
5427+
QVariant QgsExpression::NodeFunction::evalNode( QgsExpression *parent, const QgsExpressionContext *context )
54045428
{
54055429
QString name = Functions()[mFnIndex]->name();
54065430
Function *fd = context && context->hasFunction( name ) ? context->function( name ) : Functions()[mFnIndex];
@@ -5476,7 +5500,7 @@ QgsExpression::NodeFunction::NodeFunction( int fnIndex, QgsExpression::NodeList
54765500
}
54775501
}
54785502

5479-
bool QgsExpression::NodeFunction::prepare( QgsExpression *parent, const QgsExpressionContext *context )
5503+
bool QgsExpression::NodeFunction::prepareNode( QgsExpression *parent, const QgsExpressionContext *context )
54805504
{
54815505
Function *fd = Functions()[mFnIndex];
54825506

@@ -5564,6 +5588,14 @@ QgsExpression::Node *QgsExpression::NodeFunction::clone() const
55645588
return new NodeFunction( mFnIndex, mArgs ? mArgs->clone() : nullptr );
55655589
}
55665590

5591+
bool QgsExpression::NodeFunction::isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const
5592+
{
5593+
Q_UNUSED( parent )
5594+
Q_UNUSED( context )
5595+
// TODO some functions are static!
5596+
return false;
5597+
}
5598+
55675599
bool QgsExpression::NodeFunction::validateParams( int fnIndex, QgsExpression::NodeList *args, QString &error )
55685600
{
55695601
if ( !args || !args->hasNamedNodes() )
@@ -5639,14 +5671,14 @@ bool QgsExpression::NodeFunction::validateParams( int fnIndex, QgsExpression::No
56395671

56405672
//
56415673

5642-
QVariant QgsExpression::NodeLiteral::eval( QgsExpression *parent, const QgsExpressionContext *context )
5674+
QVariant QgsExpression::NodeLiteral::evalNode( QgsExpression *parent, const QgsExpressionContext *context )
56435675
{
56445676
Q_UNUSED( context );
56455677
Q_UNUSED( parent );
56465678
return mValue;
56475679
}
56485680

5649-
bool QgsExpression::NodeLiteral::prepare( QgsExpression *parent, const QgsExpressionContext *context )
5681+
bool QgsExpression::NodeLiteral::prepareNode( QgsExpression *parent, const QgsExpressionContext *context )
56505682
{
56515683
Q_UNUSED( parent );
56525684
Q_UNUSED( context );
@@ -5689,9 +5721,16 @@ QgsExpression::Node *QgsExpression::NodeLiteral::clone() const
56895721
return new NodeLiteral( mValue );
56905722
}
56915723

5724+
bool QgsExpression::NodeLiteral::isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const
5725+
{
5726+
Q_UNUSED( context )
5727+
Q_UNUSED( parent )
5728+
return true;
5729+
}
5730+
56925731
//
56935732

5694-
QVariant QgsExpression::NodeColumnRef::eval( QgsExpression *parent, const QgsExpressionContext *context )
5733+
QVariant QgsExpression::NodeColumnRef::evalNode( QgsExpression *parent, const QgsExpressionContext *context )
56955734
{
56965735
Q_UNUSED( parent );
56975736
int index = mIndex;
@@ -5717,7 +5756,7 @@ QVariant QgsExpression::NodeColumnRef::eval( QgsExpression *parent, const QgsExp
57175756
return QVariant( '[' + mName + ']' );
57185757
}
57195758

5720-
bool QgsExpression::NodeColumnRef::prepare( QgsExpression *parent, const QgsExpressionContext *context )
5759+
bool QgsExpression::NodeColumnRef::prepareNode( QgsExpression *parent, const QgsExpressionContext *context )
57215760
{
57225761
if ( !context || !context->hasVariable( QgsExpressionContext::EXPR_FIELDS ) )
57235762
return false;
@@ -5739,7 +5778,7 @@ bool QgsExpression::NodeColumnRef::prepare( QgsExpression *parent, const QgsExpr
57395778

57405779
QString QgsExpression::NodeColumnRef::dump() const
57415780
{
5742-
return QRegExp( "^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ).exactMatch( mName ) ? mName : quotedColumnRef( mName );
5781+
return quotedColumnRef( mName );
57435782
}
57445783

57455784
QSet<QString> QgsExpression::NodeColumnRef::referencedColumns() const
@@ -5757,9 +5796,16 @@ QgsExpression::Node *QgsExpression::NodeColumnRef::clone() const
57575796
return new NodeColumnRef( mName );
57585797
}
57595798

5799+
bool QgsExpression::NodeColumnRef::isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const
5800+
{
5801+
Q_UNUSED( context )
5802+
Q_UNUSED( parent )
5803+
return false;
5804+
}
5805+
57605806
//
57615807

5762-
QVariant QgsExpression::NodeCondition::eval( QgsExpression *parent, const QgsExpressionContext *context )
5808+
QVariant QgsExpression::NodeCondition::evalNode( QgsExpression *parent, const QgsExpressionContext *context )
57635809
{
57645810
Q_FOREACH ( WhenThen *cond, mConditions )
57655811
{
@@ -5785,7 +5831,7 @@ QVariant QgsExpression::NodeCondition::eval( QgsExpression *parent, const QgsExp
57855831
return QVariant();
57865832
}
57875833

5788-
bool QgsExpression::NodeCondition::prepare( QgsExpression *parent, const QgsExpressionContext *context )
5834+
bool QgsExpression::NodeCondition::prepareNode( QgsExpression *parent, const QgsExpressionContext *context )
57895835
{
57905836
bool res;
57915837
Q_FOREACH ( WhenThen *cond, mConditions )
@@ -5865,6 +5911,17 @@ QgsExpression::Node *QgsExpression::NodeCondition::clone() const
58655911
return new NodeCondition( conditions, mElseExp ? mElseExp->clone() : nullptr );
58665912
}
58675913

5914+
bool QgsExpression::NodeCondition::isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const
5915+
{
5916+
Q_FOREACH ( WhenThen *wt, mConditions )
5917+
{
5918+
if ( !wt->mWhenExp->isStatic( parent, context ) || !wt->mThenExp->isStatic( parent, context ) )
5919+
return false;
5920+
}
5921+
5922+
return mElseExp->isStatic( parent, context );
5923+
}
5924+
58685925

58695926
QString QgsExpression::helpText( QString name )
58705927
{
@@ -6269,3 +6326,29 @@ QSet<QString> QgsExpression::StaticFunction::referencedColumns( const NodeFuncti
62696326
else
62706327
return mReferencedColumns;
62716328
}
6329+
6330+
QVariant QgsExpression::Node::eval( QgsExpression *parent, const QgsExpressionContext *context )
6331+
{
6332+
if ( mStaticValue.isValid() )
6333+
{
6334+
return mStaticValue;
6335+
}
6336+
else
6337+
{
6338+
QVariant res = evalNode( parent, context );
6339+
return res;
6340+
}
6341+
}
6342+
6343+
bool QgsExpression::Node::prepare( QgsExpression *parent, const QgsExpressionContext *context )
6344+
{
6345+
if ( isStatic( parent, context ) )
6346+
{
6347+
mStaticValue = evalNode( parent, context );
6348+
return true;
6349+
}
6350+
else
6351+
{
6352+
return prepareNode( parent, context );
6353+
}
6354+
}

0 commit comments

Comments
 (0)