QGIS API Documentation 3.41.0-Master (fda2aa46e9a)
Loading...
Searching...
No Matches
qgsfeaturerequest.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsfeaturerequest.cpp
3 ---------------------
4 begin : Mai 2012
5 copyright : (C) 2012 by Martin Dobias
6 email : wonder dot sk at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15#include "qgsfeaturerequest.h"
16
17#include "qgsfields.h"
18#include "qgsgeometry.h"
19#include "qgsgeometryengine.h"
20
21#include <QStringList>
22
23//constants
24const QString QgsFeatureRequest::ALL_ATTRIBUTES = QStringLiteral( "#!allattributes!#" );
25
29
31
33 : mFilter( Qgis::FeatureRequestFilterType::Fid )
34 , mFilterFid( fid )
35{
36}
37
39 : mFilter( Qgis::FeatureRequestFilterType::Fids )
40 , mFilterFids( fids )
41{
42
43}
44
46 : mSpatialFilter( !rect.isNull() ? Qgis::SpatialFilterType::BoundingBox : Qgis::SpatialFilterType::NoFilter )
47 , mFilterRect( rect )
48{
49}
50
52 : mFilter( Qgis::FeatureRequestFilterType::Expression )
53 , mFilterExpression( new QgsExpression( expr ) )
54 , mExpressionContext( context )
55{
56}
57
62
101
102// Relaxed Equality operator
104{
105 if ( &rh == this )
106 return true;
107
108 return mFlags == rh.mFlags &&
109 mFilter == rh.mFilter &&
111 mFilterRect == rh.mFilterRect &&
114 mFilterFid == rh.mFilterFid &&
115 mFilterFids == rh.mFilterFids &&
118 mAttrs == rh.mAttrs &&
120 mLimit == rh.mLimit &&
121 mOrderBy == rh.mOrderBy &&
122 mTransform == rh.mTransform &&
123 mCrs == rh.mCrs &&
125 mTimeout == rh.mTimeout &&
127}
128
129
145
150
169
176
183
189
190QgsFeatureRequest &QgsFeatureRequest::setInvalidGeometryCallback( const std::function<void ( const QgsFeature & )> &callback )
191{
192 mInvalidGeometryCallback = callback;
193 return *this;
194}
195
197{
199 mFilterExpression.reset( new QgsExpression( expression ) );
200 return *this;
201}
202
204{
205 if ( mFilterExpression )
206 {
207 setFilterExpression( QStringLiteral( "(%1) AND (%2)" ).arg( mFilterExpression->expression(), expression ) );
208 }
209 else
210 {
211 setFilterExpression( expression );
212 }
213 return *this;
214}
215
217{
218 mExpressionContext = context;
219 return *this;
220}
221
222QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending )
223{
224 mOrderBy.append( OrderByClause( expression, ascending ) );
225 return *this;
226}
227
228QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending, bool nullsfirst )
229{
230 mOrderBy.append( OrderByClause( expression, ascending, nullsfirst ) );
231 return *this;
232}
233
238
244
246{
247 mLimit = limit;
248 return *this;
249}
250
256
263
268
269QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QStringList &attrNames, const QgsFields &fields )
270{
271 if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
272 {
273 //attribute string list contains the all attributes flag, so we must fetch all attributes
274 return *this;
275 }
276
278 mAttrs.clear();
279
280 const auto constAttrNames = attrNames;
281 for ( const QString &attrName : constAttrNames )
282 {
283 const int attrNum = fields.lookupField( attrName );
284 if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
285 mAttrs.append( attrNum );
286 }
287
288 return *this;
289}
290
291QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QSet<QString> &attrNames, const QgsFields &fields )
292{
293 if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
294 {
295 //attribute string list contains the all attributes flag, so we must fetch all attributes
296 return *this;
297 }
298
300 mAttrs.clear();
301
302 const auto constAttrNames = attrNames;
303 for ( const QString &attrName : constAttrNames )
304 {
305 const int attrNum = fields.lookupField( attrName );
306 if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
307 mAttrs.append( attrNum );
308 }
309
310 return *this;
311}
312
318
323
328
333
335{
336 if ( mTransform.isValid() )
337 {
338 return mTransform;
339 }
340 else if ( sourceCrs.isValid() && mCrs != sourceCrs )
341 {
342 return QgsCoordinateTransform( sourceCrs, mCrs, mTransformContext );
343 }
344 return QgsCoordinateTransform();
345}
346
348{
349 mTransform = transform;
350 return *this;
351}
352
359
360QgsFeatureRequest &QgsFeatureRequest::setTransformErrorCallback( const std::function<void ( const QgsFeature & )> &callback )
361{
362 mTransformErrorCallback = callback;
363 return *this;
364}
365
367{
368 // check the attribute/id filter first, it's more likely to be faster than
369 // the spatial filter
370 switch ( mFilter )
371 {
373 break;
374
376 if ( feature.id() != mFilterFid )
377 return false;
378 break;
379
382 if ( !mFilterExpression->evaluate( &mExpressionContext ).toBool() )
383 return false;
384 break;
385
387 if ( !mFilterFids.contains( feature.id() ) )
388 return false;
389 break;
390 }
391
392 switch ( mSpatialFilter )
393 {
395 break;
396
398 if ( !feature.hasGeometry() ||
399 (
401 ||
403 )
404 )
405 return false;
406 break;
407
409 if ( !feature.hasGeometry()
412 || !mReferenceGeometryEngine->distanceWithin( feature.geometry().constGet(), mDistanceWithin )
413 )
414 return false;
415 break;
416 }
417
418 return true;
419}
420
422{
423 return mTimeout;
424}
425
427{
429 return *this;
430}
431
433{
434 return mTimeout;
435}
436
438{
440 return *this;
441}
442
447
449{
451 return *this;
452}
453
458
460{
461 return mFeedback;
462}
463
464
465#include "qgsfeatureiterator.h"
466#include "qgslogger.h"
467
469{
470 while ( !mActiveIterators.empty() )
471 {
473 QgsDebugMsgLevel( QStringLiteral( "closing active iterator" ), 2 );
474 it->close();
475 }
476}
477
482
487
488
489
490QgsFeatureRequest::OrderByClause::OrderByClause( const QString &expression, bool ascending )
491 : mExpression( expression )
492 , mAscending( ascending )
493{
494 // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
495 mNullsFirst = !ascending;
496}
497
498QgsFeatureRequest::OrderByClause::OrderByClause( const QString &expression, bool ascending, bool nullsfirst )
499 : mExpression( expression )
500 , mAscending( ascending )
501 , mNullsFirst( nullsfirst )
502{
503}
504
506 : mExpression( expression )
507 , mAscending( ascending )
508{
509 // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
510 mNullsFirst = !ascending;
511}
512
513QgsFeatureRequest::OrderByClause::OrderByClause( const QgsExpression &expression, bool ascending, bool nullsfirst )
514 : mExpression( expression )
515 , mAscending( ascending )
516 , mNullsFirst( nullsfirst )
517{
518
519}
520
522{
523 return mAscending;
524}
525
527{
528 mAscending = ascending;
529}
530
532{
533 return mNullsFirst;
534}
535
537{
538 mNullsFirst = nullsFirst;
539}
540
542{
543 return QStringLiteral( "%1 %2 %3" )
544 .arg( mExpression.expression(),
545 mAscending ? "ASC" : "DESC",
546 mNullsFirst ? "NULLS FIRST" : "NULLS LAST" );
547}
548
550{
551 return mExpression;
552}
553
555{
556 return mExpression.prepare( context );
557}
558
560
561QgsFeatureRequest::OrderBy::OrderBy( const QList<QgsFeatureRequest::OrderByClause> &other )
562{
563 const auto constOther = other;
564 for ( const QgsFeatureRequest::OrderByClause &clause : constOther )
565 {
566 append( clause );
567 }
568}
569
571{
572 if ( this == &other )
573 return true;
574 if ( size() != other.size() )
575 return false;
576 for ( int i = 0; i < size(); ++i )
577 {
578 if ( at( i ) != other.at( i ) )
579 return false;
580 }
581 return true;
582}
583
585{
586 return !operator==( other );
587}
588
589QList<QgsFeatureRequest::OrderByClause> QgsFeatureRequest::OrderBy::list() const
590{
591 return *this;
592}
593
594void QgsFeatureRequest::OrderBy::save( QDomElement &elem ) const
595{
596 QDomDocument doc = elem.ownerDocument();
597 QList<OrderByClause>::ConstIterator it;
598 for ( it = constBegin(); it != constEnd(); ++it )
599 {
600 const OrderByClause &clause = *it;
601 QDomElement clauseElem = doc.createElement( QStringLiteral( "orderByClause" ) );
602 clauseElem.setAttribute( QStringLiteral( "asc" ), clause.ascending() );
603 clauseElem.setAttribute( QStringLiteral( "nullsFirst" ), clause.nullsFirst() );
604 clauseElem.appendChild( doc.createTextNode( clause.expression().expression() ) );
605
606 elem.appendChild( clauseElem );
607 }
608}
609
610void QgsFeatureRequest::OrderBy::load( const QDomElement &elem )
611{
612 clear();
613
614 const QDomNodeList clauses = elem.childNodes();
615
616 for ( int i = 0; i < clauses.size(); ++i )
617 {
618 const QDomElement clauseElem = clauses.at( i ).toElement();
619 const QString expression = clauseElem.text();
620 const bool asc = clauseElem.attribute( QStringLiteral( "asc" ) ).toInt() != 0;
621 const bool nullsFirst = clauseElem.attribute( QStringLiteral( "nullsFirst" ) ).toInt() != 0;
622
623 append( OrderByClause( expression, asc, nullsFirst ) );
624 }
625}
626
628{
629 QSet<QString> usedAttributes;
630
631 QList<OrderByClause>::ConstIterator it;
632 for ( it = constBegin(); it != constEnd(); ++it )
633 {
634 const OrderByClause &clause = *it;
635
636 usedAttributes.unite( clause.expression().referencedColumns() );
637 }
638
639 return usedAttributes;
640}
641
643{
644 QSet<int> usedAttributeIdx;
645 for ( const OrderByClause &clause : *this )
646 {
647 const auto referencedColumns = clause.expression().referencedColumns();
648 for ( const QString &fieldName : referencedColumns )
649 {
650 const int idx = fields.lookupField( fieldName );
651 if ( idx >= 0 )
652 {
653 usedAttributeIdx.insert( idx );
654 }
655 }
656 }
657 return usedAttributeIdx;
658}
659
661{
662 QStringList results;
663
664 QList<OrderByClause>::ConstIterator it;
665 for ( it = constBegin(); it != constEnd(); ++it )
666 {
667 const OrderByClause &clause = *it;
668
669 results << clause.dump();
670 }
671
672 return results.join( QLatin1String( ", " ) );
673}
The Qgis class provides global constants for use throughout the application.
Definition qgis.h:54
@ Fid
Filter using feature ID.
@ Fids
Filter using feature IDs.
@ Expression
Filter using expression.
@ NoFilter
No filter is applied.
@ ExactIntersect
Use exact geometry intersection (slower) instead of bounding boxes.
@ SubsetOfAttributes
Fetch only a subset of attributes (setSubsetOfAttributes sets this flag)
@ DistanceWithin
Filter by distance to reference geometry.
@ BoundingBox
Filter using a bounding box.
@ NoFilter
No spatial filtering of features.
QFlags< FeatureRequestFlag > FeatureRequestFlags
Flags for controlling feature requests.
Definition qgis.h:2045
InvalidGeometryCheck
Methods for handling of features with invalid geometries.
Definition qgis.h:2072
Internal feature iterator to be implemented within data providers.
virtual bool close()=0
Call to end the iteration.
void iteratorOpened(QgsAbstractFeatureIterator *it)
void iteratorClosed(QgsAbstractFeatureIterator *it)
QSet< QgsAbstractFeatureIterator * > mActiveIterators
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Contains information about the context in which a coordinate transform is executed.
Class for doing transforms between two map coordinate systems.
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Class for parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
QString expression() const
Returns the original, unmodified expression string.
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
OrderByClause(const QString &expression, bool ascending=true)
Creates a new OrderByClause for a QgsFeatureRequest.
QString dump() const
Dumps the content to an SQL equivalent.
QgsExpression expression() const
The expression.
bool ascending() const
Order ascending.
bool nullsFirst() const
Set if NULLS should be returned first.
void setAscending(bool ascending)
Set if ascending order is requested.
bool prepare(QgsExpressionContext *context)
Prepare the expression with the given context.
void setNullsFirst(bool nullsFirst)
Set if NULLS should be returned first.
Represents a list of OrderByClauses, with the most important first and the least important last.
QSet< int > CORE_EXPORT usedAttributeIndices(const QgsFields &fields) const
Returns a set of used, validated attribute indices.
CORE_EXPORT bool operator==(const OrderBy &v) const
Equality operator.
QSet< QString > CORE_EXPORT usedAttributes() const
Returns a set of used attributes.
void CORE_EXPORT load(const QDomElement &elem)
Deserialize from XML.
QList< QgsFeatureRequest::OrderByClause > CORE_EXPORT list() const
Gets a copy as a list of OrderByClauses.
QString CORE_EXPORT dump() const
Dumps the content to an SQL equivalent syntax.
CORE_EXPORT OrderBy()
Create a new empty order by.
CORE_EXPORT bool operator!=(const OrderBy &v) const
Inequality operator.
void CORE_EXPORT save(QDomElement &elem) const
Serialize to XML.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
std::unique_ptr< QgsExpression > mFilterExpression
QgsCoordinateReferenceSystem mCrs
QgsFeatureRequest & setCoordinateTransform(const QgsCoordinateTransform &transform)
Sets the coordinate transform which will be used to transform the feature's geometries.
Qgis::InvalidGeometryCheck mInvalidGeometryFilter
QgsFeatureRequest & setSimplifyMethod(const QgsSimplifyMethod &simplifyMethod)
Set a simplification method for geometries that will be fetched.
Qgis::FeatureRequestFlags mFlags
QgsRectangle filterRect() const
Returns the rectangle from which features will be taken.
QgsCoordinateTransformContext mTransformContext
Q_DECL_DEPRECATED QgsFeatureRequest & setConnectionTimeout(int connectionTimeout)
Sets the timeout (in milliseconds) for how long we should wait for a connection if none is available ...
QgsCoordinateTransform mTransform
QgsRectangle mFilterRect
Bounding box for spatial filtering.
Qgis::SpatialFilterType mSpatialFilter
Spatial filter type.
Qgis::FeatureRequestFilterType mFilter
Attribute/ID filter type.
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly by the iterator to check if it should be ca...
QgsFeatureRequest & setRequestMayBeNested(bool requestMayBeNested)
In case this request may be run nested within another already running iteration on the same connectio...
long long limit() const
Returns the maximum number of features to request, or -1 if no limit set.
QgsFeatureRequest & combineFilterExpression(const QString &expression)
Modifies the existing filter expression to add an additional expression filter.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
OrderBy orderBy() const
Returns a list of order by clauses specified for this feature request.
QgsFeatureIds mFilterFids
QgsGeometry mReferenceGeometry
Reference geometry for Qgis::RequestSpatialFilter::DistanceWithin filtering.
QgsFeatureRequest & addOrderBy(const QString &expression, bool ascending=true)
Adds a new OrderByClause, appending it as the least important one.
QgsFeatureRequest & setTimeout(int timeout)
Sets the timeout (in milliseconds) for the maximum time we should wait during feature requests before...
static const QString ALL_ATTRIBUTES
A special attribute that if set matches all attributes.
QgsExpressionContext mExpressionContext
Qgis::FeatureRequestFlags flags() const
Returns the flags which affect how features are fetched.
QgsSimplifyMethod mSimplifyMethod
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
int timeout() const
Returns the timeout (in milliseconds) for the maximum time we should wait during feature requests bef...
std::function< void(const QgsFeature &) > mTransformErrorCallback
QgsFeatureRequest & setDestinationCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets the destination crs for feature's geometries.
QgsFeatureRequest & setInvalidGeometryCheck(Qgis::InvalidGeometryCheck check)
Sets invalid geometry checking behavior.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
void setFeedback(QgsFeedback *feedback)
Attach a feedback object that can be queried regularly by the iterator to check if it should be cance...
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for feature's geometries, or an invalid QgsCoordi...
QgsCoordinateTransform coordinateTransform() const
Returns the coordinate transform which will be used to transform the feature's geometries.
QgsAttributeList mAttrs
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
bool acceptFeature(const QgsFeature &feature)
Check if a feature is accepted by this requests filter.
std::shared_ptr< QgsGeometryEngine > mReferenceGeometryEngine
Prepared geometry engine for mReferenceGeometry.
const QgsSimplifyMethod & simplifyMethod() const
Returns the simplification method for geometries that will be fetched.
std::function< void(const QgsFeature &) > mInvalidGeometryCallback
Q_DECL_DEPRECATED int connectionTimeout() const
Returns the timeout (in milliseconds) for how long we should wait for a connection if none is availab...
QgsCoordinateTransformContext transformContext() const
Returns the transform context, for use when a destinationCrs() has been set and reprojection is requi...
QgsCoordinateTransform calculateTransform(const QgsCoordinateReferenceSystem &sourceCrs) const
Calculates the coordinate transform to use to transform geometries when they are originally in source...
QgsFeatureRequest & setInvalidGeometryCallback(const std::function< void(const QgsFeature &)> &callback)
Sets a callback function to use when encountering an invalid geometry and invalidGeometryCheck() is s...
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
QgsFeatureRequest & operator=(const QgsFeatureRequest &rh)
QgsFeatureRequest & setOrderBy(const OrderBy &orderBy)
Set a list of order by clauses.
QgsFeatureRequest & setTransformErrorCallback(const std::function< void(const QgsFeature &)> &callback)
Sets a callback function to use when encountering a transform error when iterating features and a des...
double mDistanceWithin
Maximum distance from reference geometry.
bool requestMayBeNested() const
In case this request may be run nested within another already running iteration on the same connectio...
bool compare(const QgsFeatureRequest &other) const
Compare two requests for equality, ignoring Expression Context, Transform Error Callback,...
QgsFeatureRequest()
construct a default request: for all features get attributes and geometries
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Sets the feature ID that should be fetched.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
QgsFeatureRequest & setDistanceWithin(const QgsGeometry &geometry, double distance)
Sets a reference geometry and a maximum distance from this geometry to retrieve features within.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
QgsFeatureId id
Definition qgsfeature.h:66
QgsGeometry geometry
Definition qgsfeature.h:69
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition qgsfeedback.h:44
Container of fields for a vector layer.
Definition qgsfields.h:46
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
A geometry is the spatial representation of a feature.
bool boundingBoxIntersects(const QgsRectangle &rectangle) const
Returns true if the bounding box of this geometry intersects with a rectangle.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
bool equals(const QgsGeometry &geometry) const
Test if this geometry is exactly equal to another geometry.
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
bool intersects(const QgsRectangle &rectangle) const
Returns true if this geometry exactly intersects with a rectangle.
A rectangle specified with double values.
bool isNull() const
Test if the rectangle is null (holding no spatial information).
QgsRectangle buffered(double width) const
Gets rectangle enlarged by buffer.
This class contains information about how to simplify geometries fetched from a QgsFeatureIterator.
QSet< QgsFeatureId > QgsFeatureIds
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
bool operator==(const QgsFeatureIterator &fi1, const QgsFeatureIterator &fi2)
QList< int > QgsAttributeList
Definition qgsfield.h:27
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:39
const QgsCoordinateReferenceSystem & crs