QGIS API Documentation  3.13.0-Master (7ee85cd93c)
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  : mFlags( nullptr )
27 {
28 }
29 
31  : mFilter( FilterFid )
32  , mFilterFid( fid )
33  , mFlags( nullptr )
34 {
35 }
36 
38  : mFilter( FilterFids )
39  , mFilterFids( fids )
40  , mFlags( nullptr )
41 {
42 
43 }
44 
46  : mFilterRect( rect )
47  , mFlags( nullptr )
48 {
49 }
50 
53  , mFilterExpression( new QgsExpression( expr ) )
54  , mExpressionContext( context )
55  , mFlags( nullptr )
56 {
57 }
58 
60 {
61  operator=( rh );
62 }
63 
65 {
66  mFlags = rh.mFlags;
67  mFilter = rh.mFilter;
71  if ( rh.mFilterExpression )
72  {
74  }
75  else
76  {
77  mFilterExpression.reset( nullptr );
78  }
82  mAttrs = rh.mAttrs;
84  mLimit = rh.mLimit;
85  mOrderBy = rh.mOrderBy;
86  mCrs = rh.mCrs;
89  mTimeout = rh.mTimeout;
91  return *this;
92 }
93 
95 {
96  mFilterRect = rect;
97  return *this;
98 }
99 
101 {
102  mFilter = FilterFid;
103  mFilterFid = fid;
104  return *this;
105 }
106 
108 {
110  mFilterFids = fids;
111  return *this;
112 }
113 
115 {
116  mInvalidGeometryFilter = check;
117  return *this;
118 }
119 
120 QgsFeatureRequest &QgsFeatureRequest::setInvalidGeometryCallback( const std::function<void ( const QgsFeature & )> &callback )
121 {
122  mInvalidGeometryCallback = callback;
123  return *this;
124 }
125 
127 {
129  mFilterExpression.reset( new QgsExpression( expression ) );
130  return *this;
131 }
132 
134 {
135  if ( mFilterExpression )
136  {
137  setFilterExpression( QStringLiteral( "(%1) AND (%2)" ).arg( mFilterExpression->expression(), expression ) );
138  }
139  else
140  {
141  setFilterExpression( expression );
142  }
143  return *this;
144 }
145 
147 {
148  mExpressionContext = context;
149  return *this;
150 }
151 
152 QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending )
153 {
154  mOrderBy.append( OrderByClause( expression, ascending ) );
155  return *this;
156 }
157 
158 QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending, bool nullsfirst )
159 {
160  mOrderBy.append( OrderByClause( expression, ascending, nullsfirst ) );
161  return *this;
162 }
163 
165 {
166  return mOrderBy;
167 }
168 
170 {
171  mOrderBy = orderBy;
172  return *this;
173 }
174 
176 {
177  mLimit = limit;
178  return *this;
179 }
180 
182 {
183  mFlags = flags;
184  return *this;
185 }
186 
188 {
190  mAttrs = attrs;
191  return *this;
192 }
193 
195 {
197 }
198 
199 QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QStringList &attrNames, const QgsFields &fields )
200 {
201  if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
202  {
203  //attribute string list contains the all attributes flag, so we must fetch all attributes
204  return *this;
205  }
206 
208  mAttrs.clear();
209 
210  const auto constAttrNames = attrNames;
211  for ( const QString &attrName : constAttrNames )
212  {
213  int attrNum = fields.lookupField( attrName );
214  if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
215  mAttrs.append( attrNum );
216  }
217 
218  return *this;
219 }
220 
221 QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QSet<QString> &attrNames, const QgsFields &fields )
222 {
223  if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
224  {
225  //attribute string list contains the all attributes flag, so we must fetch all attributes
226  return *this;
227  }
228 
230  mAttrs.clear();
231 
232  const auto constAttrNames = attrNames;
233  for ( const QString &attrName : constAttrNames )
234  {
235  int attrNum = fields.lookupField( attrName );
236  if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
237  mAttrs.append( attrNum );
238  }
239 
240  return *this;
241 }
242 
244 {
246  return *this;
247 }
248 
249 
251 {
252  return mCrs;
253 }
254 
256 {
257  return mTransformContext;
258 }
259 
261 {
262  mCrs = crs;
263  mTransformContext = context;
264  return *this;
265 }
266 
267 QgsFeatureRequest &QgsFeatureRequest::setTransformErrorCallback( const std::function<void ( const QgsFeature & )> &callback )
268 {
269  mTransformErrorCallback = callback;
270  return *this;
271 }
272 
274 {
275  if ( !mFilterRect.isNull() )
276  {
277  if ( !feature.hasGeometry() ||
278  (
279  ( mFlags & ExactIntersect && !feature.geometry().intersects( mFilterRect ) )
280  ||
282  )
283  )
284  return false;
285  }
286 
287  switch ( mFilter )
288  {
290  return true;
291 
293  return ( feature.id() == mFilterFid );
294 
296  mExpressionContext.setFeature( feature );
297  return ( mFilterExpression->evaluate( &mExpressionContext ).toBool() );
298 
300  return ( mFilterFids.contains( feature.id() ) );
301  }
302 
303  return true;
304 }
305 
307 {
308  return mTimeout;
309 }
310 
312 {
314  return *this;
315 }
316 
318 {
319  return mTimeout;
320 }
321 
323 {
324  mTimeout = timeout;
325  return *this;
326 }
327 
329 {
330  return mRequestMayBeNested;
331 }
332 
334 {
336  return *this;
337 }
338 
339 
340 #include "qgsfeatureiterator.h"
341 #include "qgslogger.h"
342 
344 {
345  while ( !mActiveIterators.empty() )
346  {
347  QgsAbstractFeatureIterator *it = *mActiveIterators.begin();
348  QgsDebugMsgLevel( QStringLiteral( "closing active iterator" ), 2 );
349  it->close();
350  }
351 }
352 
354 {
355  mActiveIterators.insert( it );
356 }
357 
359 {
360  mActiveIterators.remove( it );
361 }
362 
363 
364 
365 QgsFeatureRequest::OrderByClause::OrderByClause( const QString &expression, bool ascending )
366  : mExpression( expression )
367  , mAscending( ascending )
368 {
369  // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
370  mNullsFirst = !ascending;
371 }
372 
374  : mExpression( expression )
375  , mAscending( ascending )
376  , mNullsFirst( nullsfirst )
377 {
378 }
379 
381  : mExpression( expression )
382  , mAscending( ascending )
383 {
384  // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
385  mNullsFirst = !ascending;
386 }
387 
389  : mExpression( expression )
390  , mAscending( ascending )
391  , mNullsFirst( nullsfirst )
392 {
393 
394 }
395 
397 {
398  return mAscending;
399 }
400 
402 {
403  mAscending = ascending;
404 }
405 
407 {
408  return mNullsFirst;
409 }
410 
412 {
413  mNullsFirst = nullsFirst;
414 }
415 
417 {
418  return QStringLiteral( "%1 %2 %3" )
419  .arg( mExpression.expression(),
420  mAscending ? "ASC" : "DESC",
421  mNullsFirst ? "NULLS FIRST" : "NULLS LAST" );
422 }
423 
425 {
426  return mExpression;
427 }
428 
430 {
431  return mExpression.prepare( context );
432 }
433 
435 
436 QgsFeatureRequest::OrderBy::OrderBy( const QList<QgsFeatureRequest::OrderByClause> &other )
437 {
438  const auto constOther = other;
439  for ( const QgsFeatureRequest::OrderByClause &clause : constOther )
440  {
441  append( clause );
442  }
443 }
444 
445 QList<QgsFeatureRequest::OrderByClause> QgsFeatureRequest::OrderBy::list() const
446 {
447  return *this;
448 }
449 
450 void QgsFeatureRequest::OrderBy::save( QDomElement &elem ) const
451 {
452  QDomDocument doc = elem.ownerDocument();
453  QList<OrderByClause>::ConstIterator it;
454  for ( it = constBegin(); it != constEnd(); ++it )
455  {
456  const OrderByClause &clause = *it;
457  QDomElement clauseElem = doc.createElement( QStringLiteral( "orderByClause" ) );
458  clauseElem.setAttribute( QStringLiteral( "asc" ), clause.ascending() );
459  clauseElem.setAttribute( QStringLiteral( "nullsFirst" ), clause.nullsFirst() );
460  clauseElem.appendChild( doc.createTextNode( clause.expression().expression() ) );
461 
462  elem.appendChild( clauseElem );
463  }
464 }
465 
466 void QgsFeatureRequest::OrderBy::load( const QDomElement &elem )
467 {
468  clear();
469 
470  QDomNodeList clauses = elem.childNodes();
471 
472  for ( int i = 0; i < clauses.size(); ++i )
473  {
474  QDomElement clauseElem = clauses.at( i ).toElement();
475  QString expression = clauseElem.text();
476  bool asc = clauseElem.attribute( QStringLiteral( "asc" ) ).toInt() != 0;
477  bool nullsFirst = clauseElem.attribute( QStringLiteral( "nullsFirst" ) ).toInt() != 0;
478 
479  append( OrderByClause( expression, asc, nullsFirst ) );
480  }
481 }
482 
484 {
485  QSet<QString> usedAttributes;
486 
487  QList<OrderByClause>::ConstIterator it;
488  for ( it = constBegin(); it != constEnd(); ++it )
489  {
490  const OrderByClause &clause = *it;
491 
492  usedAttributes.unite( clause.expression().referencedColumns() );
493  }
494 
495  return usedAttributes;
496 }
497 
499 {
500  QSet<int> usedAttributeIdx;
501  for ( const OrderByClause &clause : *this )
502  {
503  const auto referencedColumns = clause.expression().referencedColumns();
504  for ( const QString &fieldName : referencedColumns )
505  {
506  int idx = fields.lookupField( fieldName );
507  if ( idx >= 0 )
508  {
509  usedAttributeIdx.insert( idx );
510  }
511  }
512  }
513  return usedAttributeIdx;
514 }
515 
517 {
518  QStringList results;
519 
520  QList<OrderByClause>::ConstIterator it;
521  for ( it = constBegin(); it != constEnd(); ++it )
522  {
523  const OrderByClause &clause = *it;
524 
525  results << clause.dump();
526  }
527 
528  return results.join( QStringLiteral( ", " ) );
529 }
int lookupField(const QString &fieldName) const
Looks up field&#39;s index from the field name.
Definition: qgsfields.cpp:324
bool boundingBoxIntersects(const QgsRectangle &rectangle) const
Returns true if the bounding box of this geometry intersects with a rectangle.
Class for parsing and evaluation of expressions (formerly called "search strings").
QgsFeatureRequest & setDestinationCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets the destination crs for feature&#39;s geometries.
QgsFeatureId id
Definition: qgsfeature.h:64
QgsCoordinateReferenceSystem mCrs
QgsFeatureIds mFilterFids
virtual bool close()=0
end of iterating: free the resources / lock
A rectangle specified with double values.
Definition: qgsrectangle.h:41
long limit() const
Returns the maximum number of features to request, or -1 if no limit set.
bool nullsFirst() const
Set if NULLS should be returned first.
bool acceptFeature(const QgsFeature &feature)
Check if a feature is accepted by this requests filter.
QSet< QString > CORE_EXPORT usedAttributes() const
Returns a set of used attributes.
Filter using feature ID.
Filter using feature IDs.
QgsSimplifyMethod mSimplifyMethod
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:34
QgsFeatureRequest & setInvalidGeometryCallback(const std::function< void(const QgsFeature &)> &callback)
Sets a callback function to use when encountering an invalid geometry and invalidGeometryCheck() is s...
bool ascending() const
Order ascending.
const Flags & flags() const
QString dump() const
Dumps the content to an SQL equivalent.
void iteratorClosed(QgsAbstractFeatureIterator *it)
QgsFeatureRequest & setInvalidGeometryCheck(InvalidGeometryCheck check)
Sets invalid geometry checking behavior.
InvalidGeometryCheck mInvalidGeometryFilter
Use exact geometry intersection (slower) instead of bounding boxes.
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.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for feature&#39;s geometries, or an invalid QgsCoordi...
qint64 QgsFeatureId
Definition: qgsfeatureid.h:25
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Container of fields for a vector layer.
Definition: qgsfields.h:42
void CORE_EXPORT load(const QDomElement &elem)
Deserialize from XML.
QgsFeatureRequest & addOrderBy(const QString &expression, bool ascending=true)
Adds a new OrderByClause, appending it as the least important one.
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 ...
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
const QgsCoordinateReferenceSystem & crs
QgsFeatureRequest & operator=(const QgsFeatureRequest &rh)
Assignment operator.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
int timeout() const
Returns the timeout (in milliseconds) for the maximum time we should wait during feature requests bef...
QgsExpressionContext mExpressionContext
InvalidGeometryCheck
Handling of features with invalid geometries.
bool intersects(const QgsRectangle &rectangle) const
Returns true if this geometry exactly intersects with a rectangle.
QgsFeatureRequest & combineFilterExpression(const QString &expression)
Modifies the existing filter expression to add an additional expression filter.
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Sets feature ID that should be fetched.
CORE_EXPORT OrderBy()
Create a new empty order by.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
OrderByClause(const QString &expression, bool ascending=true)
Creates a new OrderByClause for a QgsFeatureRequest.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
std::unique_ptr< QgsExpression > mFilterExpression
Internal feature iterator to be implemented within data providers.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
bool requestMayBeNested() const
In case this request may be run nested within another already running iteration on the same connectio...
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QgsFeatureRequest()
construct a default request: for all features get attributes and geometries
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
static const QString ALL_ATTRIBUTES
A special attribute that if set matches all attributes.
QgsRectangle mFilterRect
Fetch only a subset of attributes (setSubsetOfAttributes sets this flag)
Contains information about the context in which a coordinate transform is executed.
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...
QString expression() const
Returns the original, unmodified expression string.
QgsFeatureRequest & setSimplifyMethod(const QgsSimplifyMethod &simplifyMethod)
Set a simplification method for geometries that will be fetched.
bool prepare(QgsExpressionContext *context)
Prepare the expression with the given context.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
QgsFeatureId mFilterFid
QgsExpression expression() const
The expression.
No filter is applied.
std::function< void(const QgsFeature &) > mInvalidGeometryCallback
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets feature IDs that should be fetched.
std::function< void(const QgsFeature &) > mTransformErrorCallback
QgsCoordinateTransformContext mTransformContext
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
void setAscending(bool ascending)
Set if ascending order is requested.
QgsFeatureRequest & setTimeout(int timeout)
Sets the timeout (in milliseconds) for the maximum time we should wait during feature requests before...
QgsAttributeList mAttrs
This class represents a coordinate reference system (CRS).
void CORE_EXPORT save(QDomElement &elem) const
Serialize to XML.
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:447
QgsFeatureRequest & setLimit(long limit)
Set the maximum number of features to request.
This class contains information about how to simplify geometries fetched from a QgsFeatureIterator.
QgsFeatureRequest & setOrderBy(const OrderBy &orderBy)
Set a list of order by clauses.
QgsGeometry geometry
Definition: qgsfeature.h:67
QgsFeatureRequest & setRequestMayBeNested(bool requestMayBeNested)
In case this request may be run nested within another already running iteration on the same connectio...
QList< int > QgsAttributeList
Definition: qgsfield.h:26
Q_DECL_DEPRECATED int connectionTimeout() const
Returns the timeout (in milliseconds) for how long we should wait for a connection if none is availab...
OrderBy orderBy() const
Returns a list of order by clauses specified for this feature request.
QgsCoordinateTransformContext transformContext() const
Returns the transform context, for use when a destinationCrs() has been set and reprojection is requi...
const QgsSimplifyMethod & simplifyMethod() const
Gets simplification method for geometries that will be fetched.
Represents a list of OrderByClauses, with the most important first and the least important last...
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
void iteratorOpened(QgsAbstractFeatureIterator *it)
QSet< int > CORE_EXPORT usedAttributeIndices(const QgsFields &fields) const
Returns a set of used, validated attribute indices.
void setNullsFirst(bool nullsFirst)
Set if NULLS should be returned first.