Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ref functions #62

Open
wants to merge 12 commits into
base: refFunctions
Choose a base branch
from
25 changes: 15 additions & 10 deletions src/core/expression/qgsexpressionfunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4926,8 +4926,13 @@ static QVariant executeGeomOverlay( const QVariantList &values, const QgsExpress
request.setFilterExpression( filterString ); //filter cached features
}

int limit = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ); //in expressions overlay functions throw the exception: Eval Error: Cannot convert '' to int
request.setLimit( limit );
node = QgsExpressionUtils::getNode( values.at( 3 ), parent ); //in expressions overlay functions throw the exception: Eval Error: Cannot convert '' to int

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that further optional parameters have to be interpreted as an expression and then converted to int. The result is a bit tricky, but goes.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if it is the proper way to do this....

ENSURE_NO_EVAL_ERROR
QString limitString = node->dump();
Copy link
Owner Author

@m-kuhn m-kuhn Jul 12, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to go for the following:

Suggested change
QString limitString = node->dump();
QVariant limitValue = node->eval( parent, context );
ENSURE_NO_EVAL_ERROR
qlonglong limit = QgsExpressionUtils::getIntValue( limitValue, parent );
request.setLimit( limit );

The issue is, that we need to do "lazy evaluation" in this method. We can't let the expression evaluate everything because we need to take care of the "filter" string manually and evaluate it with a different context.

if ( limitString != "NULL" ) {
int limit = QgsExpressionUtils::getIntValue( limitString, parent );
request.setLimit( limit );
}

int neighbors = 1;
/*
Expand Down Expand Up @@ -5474,7 +5479,7 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
<< QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "expression" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "filter" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true, -1 ),
<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true, QVariant(), true),
fcnGeomOverlayIntersects, QStringLiteral( "GeometryGroup" ), QString(), false, QSet<QString>() << QgsFeatureRequest::ALL_ATTRIBUTES, true );
// The current feature is accessed for the geometry, so this should not be cached
fcnGeomOverlayIntersectsFunc->setIsStatic( false );
Expand All @@ -5493,7 +5498,7 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
<< QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "expression" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "filter" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true, -1 ),
<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true, QVariant() ),
// TODO: limit param
fcnGeomOverlayContains, QStringLiteral( "GeometryGroup" ), QString(), false, QSet<QString>() << QgsFeatureRequest::ALL_ATTRIBUTES, true );
// The current feature is accessed for the geometry, so this should not be cached
Expand All @@ -5513,7 +5518,7 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
<< QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "expression" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "filter" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true, -1 ),
<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true, QVariant() ),
fcnGeomOverlayCrosses, QStringLiteral( "GeometryGroup" ), QString(), false, QSet<QString>() << QgsFeatureRequest::ALL_ATTRIBUTES, true );
// The current feature is accessed for the geometry, so this should not be cached
fcnGeomOverlayCrossesFunc->setIsStatic( false );
Expand All @@ -5532,7 +5537,7 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
<< QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "expression" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "filter" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true, -1 ),
<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true, QVariant() ),
fcnGeomOverlayEquals, QStringLiteral( "GeometryGroup" ), QString(), false, QSet<QString>() << QgsFeatureRequest::ALL_ATTRIBUTES, true );
// The current feature is accessed for the geometry, so this should not be cached
fcnGeomOverlayEqualsFunc->setIsStatic( false );
Expand All @@ -5551,7 +5556,7 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
<< QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "expression" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "filter" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true, -1 ),
<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true, QVariant() ),
fcnGeomOverlayTouches, QStringLiteral( "GeometryGroup" ), QString(), false, QSet<QString>() << QgsFeatureRequest::ALL_ATTRIBUTES, true );
// The current feature is accessed for the geometry, so this should not be cached
fcnGeomOverlayTouchesFunc->setIsStatic( false );
Expand All @@ -5570,7 +5575,7 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
<< QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "expression" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "filter" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true, -1 ),
<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true, QVariant() ),
fcnGeomOverlayDisjoint, QStringLiteral( "GeometryGroup" ), QString(), false, QSet<QString>() << QgsFeatureRequest::ALL_ATTRIBUTES, true );
// The current feature is accessed for the geometry, so this should not be cached
fcnGeomOverlayDisjointFunc->setIsStatic( false );
Expand All @@ -5589,7 +5594,7 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
<< QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "expression" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "filter" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true, -1 ),
<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true, QVariant() ),
fcnGeomOverlayWithin, QStringLiteral( "GeometryGroup" ), QString(), false, QSet<QString>() << QgsFeatureRequest::ALL_ATTRIBUTES, true );
// The current feature is accessed for the geometry, so this should not be cached
fcnGeomOverlayWithinFunc->setIsStatic( false );
Expand All @@ -5608,7 +5613,7 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
<< QgsExpressionFunction::Parameter( QStringLiteral( "layer" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "expression" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "filter" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true, -1 )
<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true, QVariant() )
<< QgsExpressionFunction::Parameter( QStringLiteral( "neighbors" ), true, 1 )
<< QgsExpressionFunction::Parameter( QStringLiteral( "max_distance" ), true, 0 ),
//<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true ),
Expand Down
3 changes: 3 additions & 0 deletions tests/src/core/testqgsoverlayexpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,13 @@ void TestQgsOverlayExpression::testOverlayExpression_data()

QTest::newRow( "intersects get geometry" ) << "geometry_overlay_intersects('rectangles', $geometry)" << "POLYGON((-120 30, -105 30, -105 20, -120 20, -120 30))" << QVariantList { QgsGeometry::fromWkt( "MultiPolygon (((-130 40, -115 40, -115 25, -130 25, -130 40)))" ) };
QTest::newRow( "intersects get ids" ) << "geometry_overlay_intersects('rectangles', $id)" << "LINESTRING(-178 52, -133 33, -64 46)" << QVariantList { 1, 2, 3 };
QTest::newRow( "intersects get ids limit 2" ) << "geometry_overlay_intersects('rectangles', $id, limit:=2)" << "LINESTRING(-178 52, -133 33, -64 46)" << QVariantList { 1, 2 };
QTest::newRow( "intersects filtered get ids" ) << "geometry_overlay_intersects('rectangles', $id, $id != 2)" << "LINESTRING(-178 52, -133 33, -64 46)" << QVariantList { 1, 3 };
QTest::newRow( "intersects filtered get ids limit 1" ) << "geometry_overlay_intersects('rectangles', $id, $id != 2, 1)" << "LINESTRING(-178 52, -133 33, -64 46)" << QVariantList { 1 };
QTest::newRow( "touches get ids" ) << "geometry_overlay_touches('rectangles',$id)" << "POLYGON((-86 54, -95 50, -81 50, -86 54))" << QVariantList { 3 };
QTest::newRow( "equals get ids" ) << "geometry_overlay_equals('rectangles',$id)" << "MULTIPOLYGON(((-160 50, -145 50, -145 35, -160 35, -160 50)))" << QVariantList { 1 };
QTest::newRow( "disjoint get ids" ) << "geometry_overlay_disjoint('rectangles',$id)" << "LINESTRING(-155 15, -122 55, -84 4)" << QVariantList { 1, 2, 3 };
QTest::newRow( "disjoint get ids limit 2" ) << "geometry_overlay_disjoint('rectangles',$id, limit:=2)" << "LINESTRING(-155 15, -122 55, -84 4)" << QVariantList { 1, 2 };
QTest::newRow( "nearest" ) << "geometry_overlay_nearest('rectangles',$id)" << "POINT(-135 38)" << QVariantList { 2 };
QTest::newRow( "nearest filtered" ) << "geometry_overlay_nearest('rectangles',$id,$id != 2)" << "POINT(-135 38)" << QVariantList { 1 };
}
Expand Down