QGIS API Documentation 3.39.0-Master (67e056379ed)
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
100
101// Relaxed Equality operator
103{
104 if ( &rh == this )
105 return true;
106
107 return mFlags == rh.mFlags &&
108 mFilter == rh.mFilter &&
110 mFilterRect == rh.mFilterRect &&
113 mFilterFid == rh.mFilterFid &&
114 mFilterFids == rh.mFilterFids &&
117 mAttrs == rh.mAttrs &&
119 mLimit == rh.mLimit &&
120 mOrderBy == rh.mOrderBy &&
121 mCrs == rh.mCrs &&
123 mTimeout == rh.mTimeout &&
125
126}
127
128
144
149
168
175
182
188
189QgsFeatureRequest &QgsFeatureRequest::setInvalidGeometryCallback( const std::function<void ( const QgsFeature & )> &callback )
190{
191 mInvalidGeometryCallback = callback;
192 return *this;
193}
194
196{
198 mFilterExpression.reset( new QgsExpression( expression ) );
199 return *this;
200}
201
203{
204 if ( mFilterExpression )
205 {
206 setFilterExpression( QStringLiteral( "(%1) AND (%2)" ).arg( mFilterExpression->expression(), expression ) );
207 }
208 else
209 {
210 setFilterExpression( expression );
211 }
212 return *this;
213}
214
216{
217 mExpressionContext = context;
218 return *this;
219}
220
221QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending )
222{
223 mOrderBy.append( OrderByClause( expression, ascending ) );
224 return *this;
225}
226
227QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending, bool nullsfirst )
228{
229 mOrderBy.append( OrderByClause( expression, ascending, nullsfirst ) );
230 return *this;
231}
232
237
243
245{
246 mLimit = limit;
247 return *this;
248}
249
255
262
267
268QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QStringList &attrNames, const QgsFields &fields )
269{
270 if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
271 {
272 //attribute string list contains the all attributes flag, so we must fetch all attributes
273 return *this;
274 }
275
277 mAttrs.clear();
278
279 const auto constAttrNames = attrNames;
280 for ( const QString &attrName : constAttrNames )
281 {
282 const int attrNum = fields.lookupField( attrName );
283 if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
284 mAttrs.append( attrNum );
285 }
286
287 return *this;
288}
289
290QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QSet<QString> &attrNames, const QgsFields &fields )
291{
292 if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
293 {
294 //attribute string list contains the all attributes flag, so we must fetch all attributes
295 return *this;
296 }
297
299 mAttrs.clear();
300
301 const auto constAttrNames = attrNames;
302 for ( const QString &attrName : constAttrNames )
303 {
304 const int attrNum = fields.lookupField( attrName );
305 if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
306 mAttrs.append( attrNum );
307 }
308
309 return *this;
310}
311
317
318
323
328
335
336QgsFeatureRequest &QgsFeatureRequest::setTransformErrorCallback( const std::function<void ( const QgsFeature & )> &callback )
337{
338 mTransformErrorCallback = callback;
339 return *this;
340}
341
343{
344 // check the attribute/id filter first, it's more likely to be faster than
345 // the spatial filter
346 switch ( mFilter )
347 {
349 break;
350
352 if ( feature.id() != mFilterFid )
353 return false;
354 break;
355
358 if ( !mFilterExpression->evaluate( &mExpressionContext ).toBool() )
359 return false;
360 break;
361
363 if ( !mFilterFids.contains( feature.id() ) )
364 return false;
365 break;
366 }
367
368 switch ( mSpatialFilter )
369 {
371 break;
372
374 if ( !feature.hasGeometry() ||
375 (
377 ||
379 )
380 )
381 return false;
382 break;
383
385 if ( !feature.hasGeometry()
388 || !mReferenceGeometryEngine->distanceWithin( feature.geometry().constGet(), mDistanceWithin )
389 )
390 return false;
391 break;
392 }
393
394 return true;
395}
396
398{
399 return mTimeout;
400}
401
403{
405 return *this;
406}
407
409{
410 return mTimeout;
411}
412
414{
416 return *this;
417}
418
423
425{
427 return *this;
428}
429
434
436{
437 return mFeedback;
438}
439
440
441#include "qgsfeatureiterator.h"
442#include "qgslogger.h"
443
445{
446 while ( !mActiveIterators.empty() )
447 {
449 QgsDebugMsgLevel( QStringLiteral( "closing active iterator" ), 2 );
450 it->close();
451 }
452}
453
458
463
464
465
466QgsFeatureRequest::OrderByClause::OrderByClause( const QString &expression, bool ascending )
467 : mExpression( expression )
468 , mAscending( ascending )
469{
470 // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
471 mNullsFirst = !ascending;
472}
473
474QgsFeatureRequest::OrderByClause::OrderByClause( const QString &expression, bool ascending, bool nullsfirst )
475 : mExpression( expression )
476 , mAscending( ascending )
477 , mNullsFirst( nullsfirst )
478{
479}
480
482 : mExpression( expression )
483 , mAscending( ascending )
484{
485 // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
486 mNullsFirst = !ascending;
487}
488
489QgsFeatureRequest::OrderByClause::OrderByClause( const QgsExpression &expression, bool ascending, bool nullsfirst )
490 : mExpression( expression )
491 , mAscending( ascending )
492 , mNullsFirst( nullsfirst )
493{
494
495}
496
498{
499 return mAscending;
500}
501
503{
504 mAscending = ascending;
505}
506
508{
509 return mNullsFirst;
510}
511
513{
514 mNullsFirst = nullsFirst;
515}
516
518{
519 return QStringLiteral( "%1 %2 %3" )
520 .arg( mExpression.expression(),
521 mAscending ? "ASC" : "DESC",
522 mNullsFirst ? "NULLS FIRST" : "NULLS LAST" );
523}
524
526{
527 return mExpression;
528}
529
531{
532 return mExpression.prepare( context );
533}
534
536
537QgsFeatureRequest::OrderBy::OrderBy( const QList<QgsFeatureRequest::OrderByClause> &other )
538{
539 const auto constOther = other;
540 for ( const QgsFeatureRequest::OrderByClause &clause : constOther )
541 {
542 append( clause );
543 }
544}
545
547{
548 if ( this == &other )
549 return true;
550 if ( size() != other.size() )
551 return false;
552 for ( int i = 0; i < size(); ++i )
553 {
554 if ( at( i ) != other.at( i ) )
555 return false;
556 }
557 return true;
558}
559
561{
562 return !operator==( other );
563}
564
565QList<QgsFeatureRequest::OrderByClause> QgsFeatureRequest::OrderBy::list() const
566{
567 return *this;
568}
569
570void QgsFeatureRequest::OrderBy::save( QDomElement &elem ) const
571{
572 QDomDocument doc = elem.ownerDocument();
573 QList<OrderByClause>::ConstIterator it;
574 for ( it = constBegin(); it != constEnd(); ++it )
575 {
576 const OrderByClause &clause = *it;
577 QDomElement clauseElem = doc.createElement( QStringLiteral( "orderByClause" ) );
578 clauseElem.setAttribute( QStringLiteral( "asc" ), clause.ascending() );
579 clauseElem.setAttribute( QStringLiteral( "nullsFirst" ), clause.nullsFirst() );
580 clauseElem.appendChild( doc.createTextNode( clause.expression().expression() ) );
581
582 elem.appendChild( clauseElem );
583 }
584}
585
586void QgsFeatureRequest::OrderBy::load( const QDomElement &elem )
587{
588 clear();
589
590 const QDomNodeList clauses = elem.childNodes();
591
592 for ( int i = 0; i < clauses.size(); ++i )
593 {
594 const QDomElement clauseElem = clauses.at( i ).toElement();
595 const QString expression = clauseElem.text();
596 const bool asc = clauseElem.attribute( QStringLiteral( "asc" ) ).toInt() != 0;
597 const bool nullsFirst = clauseElem.attribute( QStringLiteral( "nullsFirst" ) ).toInt() != 0;
598
599 append( OrderByClause( expression, asc, nullsFirst ) );
600 }
601}
602
604{
605 QSet<QString> usedAttributes;
606
607 QList<OrderByClause>::ConstIterator it;
608 for ( it = constBegin(); it != constEnd(); ++it )
609 {
610 const OrderByClause &clause = *it;
611
612 usedAttributes.unite( clause.expression().referencedColumns() );
613 }
614
615 return usedAttributes;
616}
617
619{
620 QSet<int> usedAttributeIdx;
621 for ( const OrderByClause &clause : *this )
622 {
623 const auto referencedColumns = clause.expression().referencedColumns();
624 for ( const QString &fieldName : referencedColumns )
625 {
626 const int idx = fields.lookupField( fieldName );
627 if ( idx >= 0 )
628 {
629 usedAttributeIdx.insert( idx );
630 }
631 }
632 }
633 return usedAttributeIdx;
634}
635
637{
638 QStringList results;
639
640 QList<OrderByClause>::ConstIterator it;
641 for ( it = constBegin(); it != constEnd(); ++it )
642 {
643 const OrderByClause &clause = *it;
644
645 results << clause.dump();
646 }
647
648 return results.join( QLatin1String( ", " ) );
649}
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:1848
InvalidGeometryCheck
Methods for handling of features with invalid geometries.
Definition qgis.h:1875
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).
Contains information about the context in which a coordinate transform is executed.
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
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 ...
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...
QgsFeedback * mFeedback
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...
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...
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)
Assignment operator.
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)
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