QGIS API Documentation  2.99.0-Master (19b062c)
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 
51 QgsFeatureRequest::QgsFeatureRequest( const QgsExpression &expr, const QgsExpressionContext &context )
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  {
73  mFilterExpression.reset( new QgsExpression( *rh.mFilterExpression ) );
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  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 
180 {
181  mFlags = flags;
182  return *this;
183 }
184 
186 {
188  mAttrs = attrs;
189  return *this;
190 }
191 
192 QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QStringList &attrNames, const QgsFields &fields )
193 {
194  if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
195  {
196  //attribute string list contains the all attributes flag, so we must fetch all attributes
197  return *this;
198  }
199 
201  mAttrs.clear();
202 
203  Q_FOREACH ( const QString &attrName, attrNames )
204  {
205  int attrNum = fields.lookupField( attrName );
206  if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
207  mAttrs.append( attrNum );
208  }
209 
210  return *this;
211 }
212 
213 QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QSet<QString> &attrNames, const QgsFields &fields )
214 {
215  if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
216  {
217  //attribute string list contains the all attributes flag, so we must fetch all attributes
218  return *this;
219  }
220 
222  mAttrs.clear();
223 
224  Q_FOREACH ( const QString &attrName, attrNames )
225  {
226  int attrNum = fields.lookupField( attrName );
227  if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
228  mAttrs.append( attrNum );
229  }
230 
231  return *this;
232 }
233 
235 {
237  return *this;
238 }
239 
240 
242 {
243  return mCrs;
244 }
245 
247 {
248  mCrs = crs;
249  return *this;
250 }
251 
252 QgsFeatureRequest &QgsFeatureRequest::setTransformErrorCallback( const std::function<void ( const QgsFeature & )> &callback )
253 {
254  mTransformErrorCallback = callback;
255  return *this;
256 }
257 
259 {
260  if ( !mFilterRect.isNull() )
261  {
262  if ( !feature.hasGeometry() || !feature.geometry().intersects( mFilterRect ) )
263  return false;
264  }
265 
266  switch ( mFilter )
267  {
269  return true;
270 
272  return ( feature.id() == mFilterFid );
273 
275  mExpressionContext.setFeature( feature );
276  return ( mFilterExpression->evaluate( &mExpressionContext ).toBool() );
277 
279  return ( mFilterFids.contains( feature.id() ) );
280  }
281 
282  return true;
283 }
284 
286 {
287  return mConnectionTimeout;
288 }
289 
291 {
293 }
294 
295 
296 #include "qgsfeatureiterator.h"
297 #include "qgslogger.h"
298 
300 {
301  while ( !mActiveIterators.empty() )
302  {
303  QgsAbstractFeatureIterator *it = *mActiveIterators.begin();
304  QgsDebugMsg( "closing active iterator" );
305  it->close();
306  }
307 }
308 
310 {
311  mActiveIterators.insert( it );
312 }
313 
315 {
316  mActiveIterators.remove( it );
317 }
318 
319 
320 
321 QgsFeatureRequest::OrderByClause::OrderByClause( const QString &expression, bool ascending )
322  : mExpression( expression )
323  , mAscending( ascending )
324 {
325  // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
326  mNullsFirst = !ascending;
327 }
328 
330  : mExpression( expression )
331  , mAscending( ascending )
332  , mNullsFirst( nullsfirst )
333 {
334 }
335 
337  : mExpression( expression )
338  , mAscending( ascending )
339 {
340  // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
341  mNullsFirst = !ascending;
342 }
343 
344 QgsFeatureRequest::OrderByClause::OrderByClause( const QgsExpression &expression, bool ascending, bool nullsfirst )
345  : mExpression( expression )
346  , mAscending( ascending )
347  , mNullsFirst( nullsfirst )
348 {
349 
350 }
351 
353 {
354  return mAscending;
355 }
356 
358 {
359  mAscending = ascending;
360 }
361 
363 {
364  return mNullsFirst;
365 }
366 
368 {
369  mNullsFirst = nullsFirst;
370 }
371 
373 {
374  return QStringLiteral( "%1 %2 %3" )
375  .arg( mExpression.expression(),
376  mAscending ? "ASC" : "DESC",
377  mNullsFirst ? "NULLS FIRST" : "NULLS LAST" );
378 }
379 
381 {
382  return mExpression;
383 }
384 
386 {
387  return mExpression.prepare( context );
388 }
389 
390 QgsFeatureRequest::OrderBy::OrderBy( const QList<QgsFeatureRequest::OrderByClause> &other )
391 {
392  Q_FOREACH ( const QgsFeatureRequest::OrderByClause &clause, other )
393  {
394  append( clause );
395  }
396 }
397 
398 QList<QgsFeatureRequest::OrderByClause> QgsFeatureRequest::OrderBy::list() const
399 {
400  return *this;
401 }
402 
403 void QgsFeatureRequest::OrderBy::save( QDomElement &elem ) const
404 {
405  QDomDocument doc = elem.ownerDocument();
406  QList<OrderByClause>::ConstIterator it;
407  for ( it = constBegin(); it != constEnd(); ++it )
408  {
409  const OrderByClause &clause = *it;
410  QDomElement clauseElem = doc.createElement( QStringLiteral( "orderByClause" ) );
411  clauseElem.setAttribute( QStringLiteral( "asc" ), clause.ascending() );
412  clauseElem.setAttribute( QStringLiteral( "nullsFirst" ), clause.nullsFirst() );
413  clauseElem.appendChild( doc.createTextNode( clause.expression().expression() ) );
414 
415  elem.appendChild( clauseElem );
416  }
417 }
418 
419 void QgsFeatureRequest::OrderBy::load( const QDomElement &elem )
420 {
421  clear();
422 
423  QDomNodeList clauses = elem.childNodes();
424 
425  for ( int i = 0; i < clauses.size(); ++i )
426  {
427  QDomElement clauseElem = clauses.at( i ).toElement();
428  QString expression = clauseElem.text();
429  bool asc = clauseElem.attribute( QStringLiteral( "asc" ) ).toInt() != 0;
430  bool nullsFirst = clauseElem.attribute( QStringLiteral( "nullsFirst" ) ).toInt() != 0;
431 
432  append( OrderByClause( expression, asc, nullsFirst ) );
433  }
434 }
435 
437 {
438  QSet<QString> usedAttributes;
439 
440  QList<OrderByClause>::ConstIterator it;
441  for ( it = constBegin(); it != constEnd(); ++it )
442  {
443  const OrderByClause &clause = *it;
444 
445  usedAttributes.unite( clause.expression().referencedColumns() );
446  }
447 
448  return usedAttributes;
449 }
450 
452 {
453  QStringList results;
454 
455  QList<OrderByClause>::ConstIterator it;
456  for ( it = constBegin(); it != constEnd(); ++it )
457  {
458  const OrderByClause &clause = *it;
459 
460  results << clause.dump();
461  }
462 
463  return results.join( QStringLiteral( ", " ) );
464 }
int lookupField(const QString &fieldName) const
Look up field&#39;s index from the field name.
Definition: qgsfields.cpp:299
QgsFeatureId id
Definition: qgsfeature.h:71
QgsCoordinateReferenceSystem mCrs
QgsFeatureIds mFilterFids
virtual bool close()=0
end of iterating: free the resources / lock
A rectangle specified with double values.
Definition: qgsrectangle.h:39
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
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 intersects(const QgsRectangle &r) const
Tests for intersection with a rectangle (uses GEOS)
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
QList< QgsFeatureRequest::OrderByClause > CORE_EXPORT list() const
Get 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.
#define QgsDebugMsg(str)
Definition: qgslogger.h:37
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:544
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for feature&#39;s geometries, or an invalid QgsCoordi...
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.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:62
QgsFeatureRequest & operator=(const QgsFeatureRequest &rh)
Assignment operator.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:190
QgsExpressionContext mExpressionContext
InvalidGeometryCheck
Handling of features with invalid geometries.
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)
Set feature ID that should be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
OrderByClause(const QString &expression, bool ascending=true)
Creates a new OrderByClause for a QgsFeatureRequest.
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...
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)
void setConnectionTimeout(int connectionTimeout)
The timeout for how long we should wait for a connection if none is available from the pool at this m...
QgsGeometry geometry() const
Returns the geometry associated with this feature.
Definition: qgsfeature.cpp:101
CORE_EXPORT OrderBy()=default
Create a new empty order by.
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...
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)
Set feature IDs that should be fetched.
std::function< void(const QgsFeature &) > mTransformErrorCallback
void setAscending(bool ascending)
Set if ascending order is requested.
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()).
QgsFeatureRequest & setLimit(long limit)
Set the maximum number of features to request.
QgsFeatureRequest & setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
Sets the destination crs for feature&#39;s geometries.
qint64 QgsFeatureId
Definition: qgsfeature.h:37
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.
QList< int > QgsAttributeList
Definition: qgsfield.h:27
int connectionTimeout() const
The timeout for how long we should wait for a connection if none is available from the pool at this m...
OrderBy orderBy() const
Return a list of order by clauses specified for this feature request.
const QgsSimplifyMethod & simplifyMethod() const
Get 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)
Set flags that affect how features will be fetched.
void iteratorOpened(QgsAbstractFeatureIterator *it)
void setNullsFirst(bool nullsFirst)
Set if NULLS should be returned first.