Skip to content

Commit

Permalink
Fix calculation of relation aggregate in virtual field with same name…
Browse files Browse the repository at this point in the history
… as related field
  • Loading branch information
nyalldawson committed Jun 20, 2018
1 parent 4132dbc commit 77d2284
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 7 deletions.
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ Represents a single parameter passed to a function.


Parameter( const QString &name, Parameter( const QString &name,
bool optional = false, bool optional = false,
const QVariant &defaultValue = QVariant() ); const QVariant &defaultValue = QVariant(),
bool isSubExpression = false );
%Docstring %Docstring
Constructor for Parameter. Constructor for Parameter.


:param name: parameter name, used when named parameter are specified in an expression :param name: parameter name, used when named parameter are specified in an expression
:param optional: set to true if parameter should be optional :param optional: set to true if parameter should be optional
:param defaultValue: default value to use for optional parameters :param defaultValue: default value to use for optional parameters
:param isSubExpression: set to true if this parameter is a sub-expression
%End %End


QString name() const; QString name() const;
Expand All @@ -60,6 +62,14 @@ Returns true if the parameter is optional.
QVariant defaultValue() const; QVariant defaultValue() const;
%Docstring %Docstring
Returns the default value for the parameter. Returns the default value for the parameter.
%End

bool isSubExpression() const;
%Docstring
Returns true if parameter argument is a separate sub-expression, and
should not be checked while determining referenced columns for the expression.

.. versionadded:: 3.2
%End %End


bool operator==( const QgsExpressionFunction::Parameter &other ) const; bool operator==( const QgsExpressionFunction::Parameter &other ) const;
Expand Down
6 changes: 3 additions & 3 deletions src/core/expression/qgsexpressionfunction.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -4113,8 +4113,8 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
QgsExpressionFunction::ParameterList() QgsExpressionFunction::ParameterList()
<< QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "aggregate" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "aggregate" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "expression" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "expression" ), false, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "filter" ), true ) << QgsExpressionFunction::Parameter( QStringLiteral( "filter" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "concatenator" ), true ), << QgsExpressionFunction::Parameter( QStringLiteral( "concatenator" ), true ),
fcnAggregate, fcnAggregate,
QStringLiteral( "Aggregates" ), QStringLiteral( "Aggregates" ),
Expand Down Expand Up @@ -4177,7 +4177,7 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
true true
) )


<< new QgsStaticExpressionFunction( QStringLiteral( "relation_aggregate" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "relation" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "aggregate" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "expression" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "concatenator" ), true ), << new QgsStaticExpressionFunction( QStringLiteral( "relation_aggregate" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "relation" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "aggregate" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "expression" ), false, QVariant(), true ) << QgsExpressionFunction::Parameter( QStringLiteral( "concatenator" ), true ),
fcnAggregateRelation, QStringLiteral( "Aggregates" ), QString(), false, QSet<QString>() << QgsFeatureRequest::ALL_ATTRIBUTES, true ) fcnAggregateRelation, QStringLiteral( "Aggregates" ), QString(), false, QSet<QString>() << QgsFeatureRequest::ALL_ATTRIBUTES, true )


<< new QgsStaticExpressionFunction( QStringLiteral( "count" ), aggParams, fcnAggregateCount, QStringLiteral( "Aggregates" ), QString(), false, QSet<QString>(), true ) << new QgsStaticExpressionFunction( QStringLiteral( "count" ), aggParams, fcnAggregateCount, QStringLiteral( "Aggregates" ), QString(), false, QSet<QString>(), true )
Expand Down
15 changes: 13 additions & 2 deletions src/core/expression/qgsexpressionfunction.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -58,13 +58,16 @@ class CORE_EXPORT QgsExpressionFunction
* \param name parameter name, used when named parameter are specified in an expression * \param name parameter name, used when named parameter are specified in an expression
* \param optional set to true if parameter should be optional * \param optional set to true if parameter should be optional
* \param defaultValue default value to use for optional parameters * \param defaultValue default value to use for optional parameters
* \param isSubExpression set to true if this parameter is a sub-expression
*/ */
Parameter( const QString &name, Parameter( const QString &name,
bool optional = false, bool optional = false,
const QVariant &defaultValue = QVariant() ) const QVariant &defaultValue = QVariant(),
bool isSubExpression = false )
: mName( name ) : mName( name )
, mOptional( optional ) , mOptional( optional )
, mDefaultValue( defaultValue ) , mDefaultValue( defaultValue )
, mIsSubExpression( isSubExpression )
{} {}


//! Returns the name of the parameter. //! Returns the name of the parameter.
Expand All @@ -76,15 +79,23 @@ class CORE_EXPORT QgsExpressionFunction
//! Returns the default value for the parameter. //! Returns the default value for the parameter.
QVariant defaultValue() const { return mDefaultValue; } QVariant defaultValue() const { return mDefaultValue; }


/**
* Returns true if parameter argument is a separate sub-expression, and
* should not be checked while determining referenced columns for the expression.
* \since QGIS 3.2
*/
bool isSubExpression() const { return mIsSubExpression; }

bool operator==( const QgsExpressionFunction::Parameter &other ) const bool operator==( const QgsExpressionFunction::Parameter &other ) const
{ {
return ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 ); return ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 );
} }


private: private:
QString mName; QString mName;
bool mOptional; bool mOptional = false;
QVariant mDefaultValue; QVariant mDefaultValue;
bool mIsSubExpression = false;
}; };


//! List of parameters, used for function definition //! List of parameters, used for function definition
Expand Down
5 changes: 4 additions & 1 deletion src/core/expression/qgsexpressionnodeimpl.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -965,10 +965,13 @@ QSet<QString> QgsExpressionNodeFunction::referencedColumns() const
return functionColumns; return functionColumns;
} }


int paramIndex = 0;
const QList< QgsExpressionNode * > nodeList = mArgs->list(); const QList< QgsExpressionNode * > nodeList = mArgs->list();
for ( QgsExpressionNode *n : nodeList ) for ( QgsExpressionNode *n : nodeList )
{ {
functionColumns.unite( n->referencedColumns() ); if ( fd->parameters().count() <= paramIndex || !fd->parameters().at( paramIndex ).isSubExpression() )
functionColumns.unite( n->referencedColumns() );
paramIndex++;
} }


return functionColumns; return functionColumns;
Expand Down
10 changes: 10 additions & 0 deletions tests/src/core/testqgsexpression.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -1843,6 +1843,16 @@ class TestQgsExpression: public QObject
refColsSet.insert( col.toLower() ); refColsSet.insert( col.toLower() );


QCOMPARE( refColsSet, expectedCols ); QCOMPARE( refColsSet, expectedCols );

expectedCols.clear();
expectedCols << QgsFeatureRequest::ALL_ATTRIBUTES
<< QStringLiteral( "parent_col1" )
<< QStringLiteral( "parent_col2" );
// sub expression fields, "child_field", "child_field2" should not be included in referenced columns
exp = QgsExpression( QStringLiteral( "relation_aggregate(relation:=\"parent_col1\" || 'my_rel',aggregate:='sum' || \"parent_col2\", expression:=\"child_field\" * \"child_field2\")" ) );
QCOMPARE( exp.hasParserError(), false );
refCols = exp.referencedColumns();
QCOMPARE( refCols, expectedCols );
} }


void referenced_variables() void referenced_variables()
Expand Down

0 comments on commit 77d2284

Please sign in to comment.