QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 
20 #include <QStringList>
21 
22 //constants
23 const QString QgsFeatureRequest::ALL_ATTRIBUTES = QStringLiteral( "#!allattributes!#" );
24 
26 {
27 }
28 
30  : mFilter( FilterFid )
31  , mFilterFid( fid )
32 {
33 }
34 
36  : mFilter( FilterFids )
37  , mFilterFids( fids )
38 {
39 
40 }
41 
43  : mFilterRect( rect )
44 {
45 }
46 
48  : mFilter( FilterExpression )
49  , mFilterExpression( new QgsExpression( expr ) )
50  , mExpressionContext( context )
51 {
52 }
53 
55 {
56  operator=( rh );
57 }
58 
60 {
61  if ( &rh == this )
62  return *this;
63 
64  mFlags = rh.mFlags;
65  mFilter = rh.mFilter;
69  if ( rh.mFilterExpression )
70  {
72  }
73  else
74  {
75  mFilterExpression.reset( nullptr );
76  }
80  mAttrs = rh.mAttrs;
82  mLimit = rh.mLimit;
83  mOrderBy = rh.mOrderBy;
84  mCrs = rh.mCrs;
87  mTimeout = rh.mTimeout;
89  return *this;
90 }
91 
93 {
94  mFilterRect = rect;
95  return *this;
96 }
97 
99 {
100  mFilter = FilterFid;
101  mFilterFid = fid;
102  return *this;
103 }
104 
106 {
108  mFilterFids = fids;
109  return *this;
110 }
111 
113 {
114  mInvalidGeometryFilter = check;
115  return *this;
116 }
117 
118 QgsFeatureRequest &QgsFeatureRequest::setInvalidGeometryCallback( const std::function<void ( const QgsFeature & )> &callback )
119 {
120  mInvalidGeometryCallback = callback;
121  return *this;
122 }
123 
125 {
127  mFilterExpression.reset( new QgsExpression( expression ) );
128  return *this;
129 }
130 
132 {
133  if ( mFilterExpression )
134  {
135  setFilterExpression( QStringLiteral( "(%1) AND (%2)" ).arg( mFilterExpression->expression(), expression ) );
136  }
137  else
138  {
139  setFilterExpression( expression );
140  }
141  return *this;
142 }
143 
145 {
146  mExpressionContext = context;
147  return *this;
148 }
149 
150 QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending )
151 {
152  mOrderBy.append( OrderByClause( expression, ascending ) );
153  return *this;
154 }
155 
156 QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending, bool nullsfirst )
157 {
158  mOrderBy.append( OrderByClause( expression, ascending, nullsfirst ) );
159  return *this;
160 }
161 
163 {
164  return mOrderBy;
165 }
166 
168 {
169  mOrderBy = orderBy;
170  return *this;
171 }
172 
174 {
175  mLimit = limit;
176  return *this;
177 }
178 
179 QgsFeatureRequest &QgsFeatureRequest::setFlags( QgsFeatureRequest::Flags flags )
180 {
181  mFlags = flags;
182  return *this;
183 }
184 
186 {
188  mAttrs = attrs;
189  return *this;
190 }
191 
193 {
195 }
196 
197 QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QStringList &attrNames, const QgsFields &fields )
198 {
199  if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
200  {
201  //attribute string list contains the all attributes flag, so we must fetch all attributes
202  return *this;
203  }
204 
206  mAttrs.clear();
207 
208  const auto constAttrNames = attrNames;
209  for ( const QString &attrName : constAttrNames )
210  {
211  int attrNum = fields.lookupField( attrName );
212  if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
213  mAttrs.append( attrNum );
214  }
215 
216  return *this;
217 }
218 
219 QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QSet<QString> &attrNames, const QgsFields &fields )
220 {
221  if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
222  {
223  //attribute string list contains the all attributes flag, so we must fetch all attributes
224  return *this;
225  }
226 
228  mAttrs.clear();
229 
230  const auto constAttrNames = attrNames;
231  for ( const QString &attrName : constAttrNames )
232  {
233  int attrNum = fields.lookupField( attrName );
234  if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
235  mAttrs.append( attrNum );
236  }
237 
238  return *this;
239 }
240 
242 {
244  return *this;
245 }
246 
247 
249 {
250  return mCrs;
251 }
252 
254 {
255  return mTransformContext;
256 }
257 
259 {
260  mCrs = crs;
261  mTransformContext = context;
262  return *this;
263 }
264 
265 QgsFeatureRequest &QgsFeatureRequest::setTransformErrorCallback( const std::function<void ( const QgsFeature & )> &callback )
266 {
267  mTransformErrorCallback = callback;
268  return *this;
269 }
270 
272 {
273  if ( !mFilterRect.isNull() )
274  {
275  if ( !feature.hasGeometry() ||
276  (
277  ( mFlags & ExactIntersect && !feature.geometry().intersects( mFilterRect ) )
278  ||
280  )
281  )
282  return false;
283  }
284 
285  switch ( mFilter )
286  {
288  return true;
289 
291  return ( feature.id() == mFilterFid );
292 
294  mExpressionContext.setFeature( feature );
295  return ( mFilterExpression->evaluate( &mExpressionContext ).toBool() );
296 
298  return ( mFilterFids.contains( feature.id() ) );
299  }
300 
301  return true;
302 }
303 
305 {
306  return mTimeout;
307 }
308 
310 {
312  return *this;
313 }
314 
316 {
317  return mTimeout;
318 }
319 
321 {
322  mTimeout = timeout;
323  return *this;
324 }
325 
327 {
328  return mRequestMayBeNested;
329 }
330 
332 {
334  return *this;
335 }
336 
337 
338 #include "qgsfeatureiterator.h"
339 #include "qgslogger.h"
340 
342 {
343  while ( !mActiveIterators.empty() )
344  {
346  QgsDebugMsgLevel( QStringLiteral( "closing active iterator" ), 2 );
347  it->close();
348  }
349 }
350 
352 {
353  mActiveIterators.insert( it );
354 }
355 
357 {
358  mActiveIterators.remove( it );
359 }
360 
361 
362 
363 QgsFeatureRequest::OrderByClause::OrderByClause( const QString &expression, bool ascending )
364  : mExpression( expression )
365  , mAscending( ascending )
366 {
367  // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
368  mNullsFirst = !ascending;
369 }
370 
371 QgsFeatureRequest::OrderByClause::OrderByClause( const QString &expression, bool ascending, bool nullsfirst )
372  : mExpression( expression )
373  , mAscending( ascending )
374  , mNullsFirst( nullsfirst )
375 {
376 }
377 
379  : mExpression( expression )
380  , mAscending( ascending )
381 {
382  // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
383  mNullsFirst = !ascending;
384 }
385 
386 QgsFeatureRequest::OrderByClause::OrderByClause( const QgsExpression &expression, bool ascending, bool nullsfirst )
387  : mExpression( expression )
388  , mAscending( ascending )
389  , mNullsFirst( nullsfirst )
390 {
391 
392 }
393 
395 {
396  return mAscending;
397 }
398 
400 {
401  mAscending = ascending;
402 }
403 
405 {
406  return mNullsFirst;
407 }
408 
410 {
411  mNullsFirst = nullsFirst;
412 }
413 
415 {
416  return QStringLiteral( "%1 %2 %3" )
417  .arg( mExpression.expression(),
418  mAscending ? "ASC" : "DESC",
419  mNullsFirst ? "NULLS FIRST" : "NULLS LAST" );
420 }
421 
423 {
424  return mExpression;
425 }
426 
428 {
429  return mExpression.prepare( context );
430 }
431 
433 
434 QgsFeatureRequest::OrderBy::OrderBy( const QList<QgsFeatureRequest::OrderByClause> &other )
435 {
436  const auto constOther = other;
437  for ( const QgsFeatureRequest::OrderByClause &clause : constOther )
438  {
439  append( clause );
440  }
441 }
442 
443 QList<QgsFeatureRequest::OrderByClause> QgsFeatureRequest::OrderBy::list() const
444 {
445  return *this;
446 }
447 
448 void QgsFeatureRequest::OrderBy::save( QDomElement &elem ) const
449 {
450  QDomDocument doc = elem.ownerDocument();
451  QList<OrderByClause>::ConstIterator it;
452  for ( it = constBegin(); it != constEnd(); ++it )
453  {
454  const OrderByClause &clause = *it;
455  QDomElement clauseElem = doc.createElement( QStringLiteral( "orderByClause" ) );
456  clauseElem.setAttribute( QStringLiteral( "asc" ), clause.ascending() );
457  clauseElem.setAttribute( QStringLiteral( "nullsFirst" ), clause.nullsFirst() );
458  clauseElem.appendChild( doc.createTextNode( clause.expression().expression() ) );
459 
460  elem.appendChild( clauseElem );
461  }
462 }
463 
464 void QgsFeatureRequest::OrderBy::load( const QDomElement &elem )
465 {
466  clear();
467 
468  QDomNodeList clauses = elem.childNodes();
469 
470  for ( int i = 0; i < clauses.size(); ++i )
471  {
472  QDomElement clauseElem = clauses.at( i ).toElement();
473  QString expression = clauseElem.text();
474  bool asc = clauseElem.attribute( QStringLiteral( "asc" ) ).toInt() != 0;
475  bool nullsFirst = clauseElem.attribute( QStringLiteral( "nullsFirst" ) ).toInt() != 0;
476 
477  append( OrderByClause( expression, asc, nullsFirst ) );
478  }
479 }
480 
482 {
483  QSet<QString> usedAttributes;
484 
485  QList<OrderByClause>::ConstIterator it;
486  for ( it = constBegin(); it != constEnd(); ++it )
487  {
488  const OrderByClause &clause = *it;
489 
490  usedAttributes.unite( clause.expression().referencedColumns() );
491  }
492 
493  return usedAttributes;
494 }
495 
497 {
498  QSet<int> usedAttributeIdx;
499  for ( const OrderByClause &clause : *this )
500  {
501  const auto referencedColumns = clause.expression().referencedColumns();
502  for ( const QString &fieldName : referencedColumns )
503  {
504  int idx = fields.lookupField( fieldName );
505  if ( idx >= 0 )
506  {
507  usedAttributeIdx.insert( idx );
508  }
509  }
510  }
511  return usedAttributeIdx;
512 }
513 
515 {
516  QStringList results;
517 
518  QList<OrderByClause>::ConstIterator it;
519  for ( it = constBegin(); it != constEnd(); ++it )
520  {
521  const OrderByClause &clause = *it;
522 
523  results << clause.dump();
524  }
525 
526  return results.join( QLatin1String( ", " ) );
527 }
Internal feature iterator to be implemented within data providers.
virtual bool close()=0
end of iterating: free the resources / lock
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").
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.
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.
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 & setLimit(long long limit)
Set the maximum number of features to request.
std::unique_ptr< QgsExpression > mFilterExpression
QgsCoordinateReferenceSystem mCrs
const QgsSimplifyMethod & simplifyMethod() const
Gets simplification method for geometries that will be fetched.
QgsFeatureRequest & setSimplifyMethod(const QgsSimplifyMethod &simplifyMethod)
Set a simplification method for geometries that will be fetched.
QgsCoordinateTransformContext mTransformContext
InvalidGeometryCheck
Handling of features with invalid geometries.
QgsFeatureId mFilterFid
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
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 feature IDs that should be fetched.
OrderBy orderBy() const
Returns a list of order by clauses specified for this feature request.
QgsFeatureIds mFilterFids
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
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
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...
InvalidGeometryCheck mInvalidGeometryFilter
std::function< void(const QgsFeature &) > mTransformErrorCallback
QgsFeatureRequest & setDestinationCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets the destination crs for feature's geometries.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for feature's geometries, or an invalid QgsCoordi...
@ SubsetOfAttributes
Fetch only a subset of attributes (setSubsetOfAttributes sets this flag)
@ ExactIntersect
Use exact geometry intersection (slower) instead of bounding boxes.
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::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 & setInvalidGeometryCheck(InvalidGeometryCheck check)
Sets invalid geometry checking behavior.
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...
bool requestMayBeNested() const
In case this request may be run nested within another already running iteration on the same connectio...
@ FilterFid
Filter using feature ID.
@ FilterFids
Filter using feature IDs.
@ FilterNone
No filter is applied.
@ FilterExpression
Filter using expression.
const Flags & flags() const
QgsFeatureRequest()
construct a default request: for all features get attributes and geometries
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Sets feature ID that should be fetched.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsGeometry geometry
Definition: qgsfeature.h:67
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:205
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
Container of fields for a vector layer.
Definition: qgsfields.h:45
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:344
bool boundingBoxIntersects(const QgsRectangle &rectangle) const
Returns true if the bounding box of this geometry intersects with a rectangle.
bool intersects(const QgsRectangle &rectangle) const
Returns true if this geometry exactly intersects with a rectangle.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:479
This class contains information about how to simplify geometries fetched from a QgsFeatureIterator.
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
QList< int > QgsAttributeList
Definition: qgsfield.h:26
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
const QgsCoordinateReferenceSystem & crs