Add referencedFunctions() to expressions

This commit is contained in:
Alessandro Pasotti 2018-05-15 09:20:10 +02:00
parent edb12b4dbe
commit b4f86147c7
10 changed files with 136 additions and 0 deletions

View File

@ -176,6 +176,13 @@ If the list contains a NULL QString, there is a variable name used
which is determined at runtime.
.. versionadded:: 3.0
%End
QSet<QString> referencedFunctions() const;
%Docstring
Return a list of all functions which are used in this expression.
.. versionadded:: 3.2
%End
QSet<int> referencedAttributeIndexes( const QgsFields &fields ) const;

View File

@ -196,6 +196,11 @@ to evaluate child nodes.
virtual QSet<QString> referencedVariables() const = 0;
%Docstring
Return a set of all variables which are used in this expression.
%End
virtual QSet<QString> referencedFunctions() const = 0;
%Docstring
Return a set of all functions which are used in this expression.
%End
virtual bool needsGeometry() const = 0;

View File

@ -55,6 +55,8 @@ Returns the node the operator will operate upon.
virtual QSet<QString> referencedVariables() const;
virtual QSet<QString> referencedFunctions() const;
virtual bool needsGeometry() const;
virtual QgsExpressionNode *clone() const /Factory/;
@ -154,6 +156,9 @@ Returns the node to the right of the operator.
virtual QSet<QString> referencedVariables() const;
virtual QSet<QString> referencedFunctions() const;
virtual bool needsGeometry() const;
virtual QgsExpressionNode *clone() const /Factory/;
@ -224,6 +229,8 @@ Returns the list of nodes to search for matching values within.
virtual QSet<QString> referencedVariables() const;
virtual QSet<QString> referencedFunctions() const;
virtual bool needsGeometry() const;
virtual QgsExpressionNode *clone() const /Factory/;
@ -275,6 +282,8 @@ Returns a list of arguments specified for the function.
virtual QSet<QString> referencedVariables() const;
virtual QSet<QString> referencedFunctions() const;
virtual bool needsGeometry() const;
virtual QgsExpressionNode *clone() const /Factory/;
@ -323,6 +332,8 @@ The value of the literal.
virtual QSet<QString> referencedVariables() const;
virtual QSet<QString> referencedFunctions() const;
virtual bool needsGeometry() const;
virtual QgsExpressionNode *clone() const /Factory/;
@ -367,6 +378,8 @@ The name of the column.
virtual QSet<QString> referencedVariables() const;
virtual QSet<QString> referencedFunctions() const;
virtual bool needsGeometry() const;
@ -466,6 +479,8 @@ The ELSE expression used for the condition.
virtual QSet<QString> referencedVariables() const;
virtual QSet<QString> referencedFunctions() const;
virtual bool needsGeometry() const;
virtual QgsExpressionNode *clone() const /Factory/;

View File

@ -276,6 +276,14 @@ QSet<QString> QgsExpression::referencedVariables() const
return d->mRootNode->referencedVariables();
}
QSet<QString> QgsExpression::referencedFunctions() const
{
if ( !d->mRootNode )
return QSet<QString>();
return d->mRootNode->referencedFunctions();
}
QSet<int> QgsExpression::referencedAttributeIndexes( const QgsFields &fields ) const
{
if ( !d->mRootNode )

View File

@ -258,6 +258,13 @@ class CORE_EXPORT QgsExpression
*/
QSet<QString> referencedVariables() const;
/**
* Return a list of all functions which are used in this expression.
*
* \since QGIS 3.2
*/
QSet<QString> referencedFunctions() const;
/**
* Return a list of field name indexes obtained from the provided fields.
*

View File

@ -57,3 +57,4 @@ void QgsExpressionNode::cloneTo( QgsExpressionNode *target ) const
target->parserFirstColumn = parserFirstColumn;
target->parserFirstLine = parserFirstLine;
}

View File

@ -222,6 +222,11 @@ class CORE_EXPORT QgsExpressionNode SIP_ABSTRACT
*/
virtual QSet<QString> referencedVariables() const = 0;
/**
* Return a set of all functions which are used in this expression.
*/
virtual QSet<QString> referencedFunctions() const = 0;
/**
* Abstract virtual method which returns if the geometry is required to evaluate
* this expression.

View File

@ -137,6 +137,11 @@ QSet<QString> QgsExpressionNodeUnaryOperator::referencedVariables() const
return mOperand->referencedVariables();
}
QSet<QString> QgsExpressionNodeUnaryOperator::referencedFunctions() const
{
return mOperand->referencedFunctions();
}
bool QgsExpressionNodeUnaryOperator::needsGeometry() const
{
return mOperand->needsGeometry();
@ -720,6 +725,11 @@ QSet<QString> QgsExpressionNodeBinaryOperator::referencedVariables() const
return mOpLeft->referencedVariables() + mOpRight->referencedVariables();
}
QSet<QString> QgsExpressionNodeBinaryOperator::referencedFunctions() const
{
return mOpLeft->referencedFunctions() + mOpRight->referencedFunctions();
}
bool QgsExpressionNodeBinaryOperator::needsGeometry() const
{
return mOpLeft->needsGeometry() || mOpRight->needsGeometry();
@ -978,6 +988,23 @@ QSet<QString> QgsExpressionNodeFunction::referencedVariables() const
}
}
QSet<QString> QgsExpressionNodeFunction::referencedFunctions() const
{
QgsExpressionFunction *fd = QgsExpression::QgsExpression::Functions()[mFnIndex];
QSet<QString> functions = QSet<QString>();
functions.insert( fd->name() );
if ( !mArgs )
return functions;
const QList< QgsExpressionNode * > nodeList = mArgs->list();
for ( QgsExpressionNode *n : nodeList )
{
functions.unite( n->referencedFunctions() );
}
return functions;
}
bool QgsExpressionNodeFunction::needsGeometry() const
{
bool needs = QgsExpression::QgsExpression::Functions()[mFnIndex]->usesGeometry( this );
@ -1128,6 +1155,11 @@ QSet<QString> QgsExpressionNodeLiteral::referencedVariables() const
return QSet<QString>();
}
QSet<QString> QgsExpressionNodeLiteral::referencedFunctions() const
{
return QSet<QString>();
}
bool QgsExpressionNodeLiteral::needsGeometry() const
{
return false;
@ -1215,6 +1247,11 @@ QSet<QString> QgsExpressionNodeColumnRef::referencedVariables() const
return QSet<QString>();
}
QSet<QString> QgsExpressionNodeColumnRef::referencedFunctions() const
{
return QSet<QString>();
}
bool QgsExpressionNodeColumnRef::needsGeometry() const
{
return false;
@ -1338,6 +1375,20 @@ QSet<QString> QgsExpressionNodeCondition::referencedVariables() const
return lst;
}
QSet<QString> QgsExpressionNodeCondition::referencedFunctions() const
{
QSet<QString> lst;
for ( WhenThen *cond : mConditions )
{
lst += cond->mWhenExp->referencedFunctions() + cond->mThenExp->referencedFunctions();
}
if ( mElseExp )
lst += mElseExp->referencedFunctions();
return lst;
}
bool QgsExpressionNodeCondition::needsGeometry() const
{
for ( WhenThen *cond : mConditions )
@ -1393,6 +1444,16 @@ QSet<QString> QgsExpressionNodeInOperator::referencedVariables() const
return lst;
}
QSet<QString> QgsExpressionNodeInOperator::referencedFunctions() const
{
QSet<QString> lst( mNode->referencedFunctions() );
const QList< QgsExpressionNode * > nodeList = mList->list();
for ( const QgsExpressionNode *n : nodeList )
lst.unite( n->referencedFunctions() );
return lst;
}
QgsExpressionNodeCondition::WhenThen::WhenThen( QgsExpressionNode *whenExp, QgsExpressionNode *thenExp )
: mWhenExp( whenExp )
, mThenExp( thenExp )
@ -1414,3 +1475,4 @@ QString QgsExpressionNodeBinaryOperator::text() const
{
return BINARY_OPERATOR_TEXT[mOp];
}

View File

@ -64,6 +64,7 @@ class CORE_EXPORT QgsExpressionNodeUnaryOperator : public QgsExpressionNode
QSet<QString> referencedColumns() const override;
QSet<QString> referencedVariables() const override;
QSet<QString> referencedFunctions() const override;
bool needsGeometry() const override;
QgsExpressionNode *clone() const override SIP_FACTORY;
@ -162,6 +163,8 @@ class CORE_EXPORT QgsExpressionNodeBinaryOperator : public QgsExpressionNode
QSet<QString> referencedColumns() const override;
QSet<QString> referencedVariables() const override;
QSet<QString> referencedFunctions() const override;
bool needsGeometry() const override;
QgsExpressionNode *clone() const override SIP_FACTORY;
bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
@ -241,6 +244,7 @@ class CORE_EXPORT QgsExpressionNodeInOperator : public QgsExpressionNode
QSet<QString> referencedColumns() const override;
QSet<QString> referencedVariables() const override;
QSet<QString> referencedFunctions() const override;
bool needsGeometry() const override;
QgsExpressionNode *clone() const override SIP_FACTORY;
bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
@ -284,6 +288,7 @@ class CORE_EXPORT QgsExpressionNodeFunction : public QgsExpressionNode
QSet<QString> referencedColumns() const override;
QSet<QString> referencedVariables() const override;
QSet<QString> referencedFunctions() const override;
bool needsGeometry() const override;
QgsExpressionNode *clone() const override SIP_FACTORY;
bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
@ -321,6 +326,7 @@ class CORE_EXPORT QgsExpressionNodeLiteral : public QgsExpressionNode
QSet<QString> referencedColumns() const override;
QSet<QString> referencedVariables() const override;
QSet<QString> referencedFunctions() const override;
bool needsGeometry() const override;
QgsExpressionNode *clone() const override SIP_FACTORY;
bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
@ -356,6 +362,7 @@ class CORE_EXPORT QgsExpressionNodeColumnRef : public QgsExpressionNode
QSet<QString> referencedColumns() const override;
QSet<QString> referencedVariables() const override;
QSet<QString> referencedFunctions() const override;
bool needsGeometry() const override;
QgsExpressionNode *clone() const override SIP_FACTORY;
@ -456,6 +463,7 @@ class CORE_EXPORT QgsExpressionNodeCondition : public QgsExpressionNode
QSet<QString> referencedColumns() const override;
QSet<QString> referencedVariables() const override;
QSet<QString> referencedFunctions() const override;
bool needsGeometry() const override;
QgsExpressionNode *clone() const override SIP_FACTORY;
bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;

View File

@ -1861,6 +1861,24 @@ class TestQgsExpression: public QObject
QCOMPARE( refVar, expectedVars );
}
void referenced_functions()
{
QSet<QString> expectedFunctions;
expectedFunctions << QStringLiteral( "current_value" )
<< QStringLiteral( "var" )
<< QStringLiteral( "intersects" )
<< QStringLiteral( "$geometry" )
<< QStringLiteral( "buffer" );
QgsExpression exp( QStringLiteral( "current_value( 'FIELD_NAME' ) = \"A_VALUE\" AND intersects(buffer($geometry, 10), @current_geometry)" ) );
QCOMPARE( exp.hasParserError(), false );
QSet<QString> refVar = exp.referencedFunctions();
QCOMPARE( refVar, expectedFunctions );
}
void referenced_columns_all_attributes()
{
QgsExpression exp( QStringLiteral( "attribute($currentfeature,'test')" ) );