Skip to content

Commit

Permalink
Collapse static nodes in QgsExpression:prepare()
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
m-kuhn committed Apr 30, 2017
1 parent a8fc2c1 commit 0cc7311
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 48 deletions.
117 changes: 100 additions & 17 deletions src/core/qgsexpression.cpp
Expand Up @@ -4708,7 +4708,7 @@ QString QgsExpression::NodeList::dump() const

//

QVariant QgsExpression::NodeUnaryOperator::eval( QgsExpression *parent, const QgsExpressionContext *context )
QVariant QgsExpression::NodeUnaryOperator::evalNode( QgsExpression *parent, const QgsExpressionContext *context )
{
QVariant val = mOperand->eval( parent, context );
ENSURE_NO_EVAL_ERROR;
Expand All @@ -4735,7 +4735,7 @@ QVariant QgsExpression::NodeUnaryOperator::eval( QgsExpression *parent, const Qg
return QVariant();
}

bool QgsExpression::NodeUnaryOperator::prepare( QgsExpression *parent, const QgsExpressionContext *context )
bool QgsExpression::NodeUnaryOperator::prepareNode( QgsExpression *parent, const QgsExpressionContext *context )
{
return mOperand->prepare( parent, context );
}
Expand All @@ -4760,9 +4760,14 @@ QgsExpression::Node *QgsExpression::NodeUnaryOperator::clone() const
return new NodeUnaryOperator( mOp, mOperand->clone() );
}

bool QgsExpression::NodeUnaryOperator::isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const
{
return mOperand->isStatic( parent, context );
}

//

QVariant QgsExpression::NodeBinaryOperator::eval( QgsExpression *parent, const QgsExpressionContext *context )
QVariant QgsExpression::NodeBinaryOperator::evalNode( QgsExpression *parent, const QgsExpressionContext *context )
{
QVariant vL = mOpLeft->eval( parent, context );
ENSURE_NO_EVAL_ERROR;
Expand Down Expand Up @@ -4945,13 +4950,13 @@ QVariant QgsExpression::NodeBinaryOperator::eval( QgsExpression *parent, const Q
QgsExpression::NodeLiteral nL( lL.at( i ) );
QgsExpression::NodeLiteral nR( lR.at( i ) );
QgsExpression::NodeBinaryOperator eqNode( boEQ, nL.clone(), nR.clone() );
QVariant eq = eqNode.eval( parent, context );
QVariant eq = eqNode.evalNode( parent, context );
ENSURE_NO_EVAL_ERROR;
if ( eq == TVL_False )
{
// return the two items comparison
QgsExpression::NodeBinaryOperator node( mOp, nL.clone(), nR.clone() );
QVariant v = node.eval( parent, context );
QVariant v = node.evalNode( parent, context );
ENSURE_NO_EVAL_ERROR;
return v;
}
Expand Down Expand Up @@ -5186,7 +5191,7 @@ double QgsExpression::NodeBinaryOperator::computeDouble( double x, double y )
}
}

bool QgsExpression::NodeBinaryOperator::prepare( QgsExpression *parent, const QgsExpressionContext *context )
bool QgsExpression::NodeBinaryOperator::prepareNode( QgsExpression *parent, const QgsExpressionContext *context )
{
bool resL = mOpLeft->prepare( parent, context );
bool resR = mOpRight->prepare( parent, context );
Expand Down Expand Up @@ -5326,9 +5331,14 @@ QgsExpression::Node *QgsExpression::NodeBinaryOperator::clone() const
return new NodeBinaryOperator( mOp, mOpLeft->clone(), mOpRight->clone() );
}

bool QgsExpression::NodeBinaryOperator::isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const
{
return mOpLeft->isStatic( parent, context ) && mOpRight->isStatic( parent, context );
}

//

QVariant QgsExpression::NodeInOperator::eval( QgsExpression *parent, const QgsExpressionContext *context )
QVariant QgsExpression::NodeInOperator::evalNode( QgsExpression *parent, const QgsExpressionContext *context )
{
if ( mList->count() == 0 )
return mNotIn ? TVL_True : TVL_False;
Expand Down Expand Up @@ -5378,7 +5388,7 @@ QVariant QgsExpression::NodeInOperator::eval( QgsExpression *parent, const QgsEx
return mNotIn ? TVL_True : TVL_False;
}

bool QgsExpression::NodeInOperator::prepare( QgsExpression *parent, const QgsExpressionContext *context )
bool QgsExpression::NodeInOperator::prepareNode( QgsExpression *parent, const QgsExpressionContext *context )
{
bool res = mNode->prepare( parent, context );
Q_FOREACH ( Node *n, mList->list() )
Expand All @@ -5398,9 +5408,23 @@ QgsExpression::Node *QgsExpression::NodeInOperator::clone() const
return new NodeInOperator( mNode->clone(), mList->clone(), mNotIn );
}

bool QgsExpression::NodeInOperator::isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const
{
if ( !mNode->isStatic( parent, context ) )
return false;

Q_FOREACH ( Node *n, mList->list() )
{
if ( !n->isStatic( parent, context ) )
return false;
}

return true;
}

//

QVariant QgsExpression::NodeFunction::eval( QgsExpression *parent, const QgsExpressionContext *context )
QVariant QgsExpression::NodeFunction::evalNode( QgsExpression *parent, const QgsExpressionContext *context )
{
QString name = Functions()[mFnIndex]->name();
Function *fd = context && context->hasFunction( name ) ? context->function( name ) : Functions()[mFnIndex];
Expand Down Expand Up @@ -5476,7 +5500,7 @@ QgsExpression::NodeFunction::NodeFunction( int fnIndex, QgsExpression::NodeList
}
}

bool QgsExpression::NodeFunction::prepare( QgsExpression *parent, const QgsExpressionContext *context )
bool QgsExpression::NodeFunction::prepareNode( QgsExpression *parent, const QgsExpressionContext *context )
{
Function *fd = Functions()[mFnIndex];

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

bool QgsExpression::NodeFunction::isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const
{
Q_UNUSED( parent )
Q_UNUSED( context )
// TODO some functions are static!
return false;
}

bool QgsExpression::NodeFunction::validateParams( int fnIndex, QgsExpression::NodeList *args, QString &error )
{
if ( !args || !args->hasNamedNodes() )
Expand Down Expand Up @@ -5639,14 +5671,14 @@ bool QgsExpression::NodeFunction::validateParams( int fnIndex, QgsExpression::No

//

QVariant QgsExpression::NodeLiteral::eval( QgsExpression *parent, const QgsExpressionContext *context )
QVariant QgsExpression::NodeLiteral::evalNode( QgsExpression *parent, const QgsExpressionContext *context )
{
Q_UNUSED( context );
Q_UNUSED( parent );
return mValue;
}

bool QgsExpression::NodeLiteral::prepare( QgsExpression *parent, const QgsExpressionContext *context )
bool QgsExpression::NodeLiteral::prepareNode( QgsExpression *parent, const QgsExpressionContext *context )
{
Q_UNUSED( parent );
Q_UNUSED( context );
Expand Down Expand Up @@ -5689,9 +5721,16 @@ QgsExpression::Node *QgsExpression::NodeLiteral::clone() const
return new NodeLiteral( mValue );
}

bool QgsExpression::NodeLiteral::isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const
{
Q_UNUSED( context )
Q_UNUSED( parent )
return true;
}

//

QVariant QgsExpression::NodeColumnRef::eval( QgsExpression *parent, const QgsExpressionContext *context )
QVariant QgsExpression::NodeColumnRef::evalNode( QgsExpression *parent, const QgsExpressionContext *context )
{
Q_UNUSED( parent );
int index = mIndex;
Expand All @@ -5717,7 +5756,7 @@ QVariant QgsExpression::NodeColumnRef::eval( QgsExpression *parent, const QgsExp
return QVariant( '[' + mName + ']' );
}

bool QgsExpression::NodeColumnRef::prepare( QgsExpression *parent, const QgsExpressionContext *context )
bool QgsExpression::NodeColumnRef::prepareNode( QgsExpression *parent, const QgsExpressionContext *context )
{
if ( !context || !context->hasVariable( QgsExpressionContext::EXPR_FIELDS ) )
return false;
Expand All @@ -5739,7 +5778,7 @@ bool QgsExpression::NodeColumnRef::prepare( QgsExpression *parent, const QgsExpr

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

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

bool QgsExpression::NodeColumnRef::isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const
{
Q_UNUSED( context )
Q_UNUSED( parent )
return false;
}

//

QVariant QgsExpression::NodeCondition::eval( QgsExpression *parent, const QgsExpressionContext *context )
QVariant QgsExpression::NodeCondition::evalNode( QgsExpression *parent, const QgsExpressionContext *context )
{
Q_FOREACH ( WhenThen *cond, mConditions )
{
Expand All @@ -5785,7 +5831,7 @@ QVariant QgsExpression::NodeCondition::eval( QgsExpression *parent, const QgsExp
return QVariant();
}

bool QgsExpression::NodeCondition::prepare( QgsExpression *parent, const QgsExpressionContext *context )
bool QgsExpression::NodeCondition::prepareNode( QgsExpression *parent, const QgsExpressionContext *context )
{
bool res;
Q_FOREACH ( WhenThen *cond, mConditions )
Expand Down Expand Up @@ -5865,6 +5911,17 @@ QgsExpression::Node *QgsExpression::NodeCondition::clone() const
return new NodeCondition( conditions, mElseExp ? mElseExp->clone() : nullptr );
}

bool QgsExpression::NodeCondition::isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const
{
Q_FOREACH ( WhenThen *wt, mConditions )
{
if ( !wt->mWhenExp->isStatic( parent, context ) || !wt->mThenExp->isStatic( parent, context ) )
return false;
}

return mElseExp->isStatic( parent, context );
}


QString QgsExpression::helpText( QString name )
{
Expand Down Expand Up @@ -6269,3 +6326,29 @@ QSet<QString> QgsExpression::StaticFunction::referencedColumns( const NodeFuncti
else
return mReferencedColumns;
}

QVariant QgsExpression::Node::eval( QgsExpression *parent, const QgsExpressionContext *context )
{
if ( mStaticValue.isValid() )
{
return mStaticValue;
}
else
{
QVariant res = evalNode( parent, context );
return res;
}
}

bool QgsExpression::Node::prepare( QgsExpression *parent, const QgsExpressionContext *context )
{
if ( isStatic( parent, context ) )
{
mStaticValue = evalNode( parent, context );
return true;
}
else
{
return prepareNode( parent, context );
}
}

0 comments on commit 0cc7311

Please sign in to comment.