QGIS API Documentation  2.99.0-Master (13a3f2f)
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  return *this;
87 }
88 
90 {
91  mFilterRect = rect;
92  return *this;
93 }
94 
96 {
98  mFilterFid = fid;
99  return *this;
100 }
101 
103 {
105  mFilterFids = fids;
106  return *this;
107 }
108 
110 {
111  mInvalidGeometryFilter = check;
112  return *this;
113 }
114 
116 {
117  mInvalidGeometryCallback = callback;
118  return *this;
119 }
120 
122 {
124  mFilterExpression.reset( new QgsExpression( expression ) );
125  return *this;
126 }
127 
129 {
130  if ( mFilterExpression )
131  {
132  setFilterExpression( QStringLiteral( "(%1) AND (%2)" ).arg( mFilterExpression->expression(), expression ) );
133  }
134  else
135  {
136  setFilterExpression( expression );
137  }
138  return *this;
139 }
140 
142 {
143  mExpressionContext = context;
144  return *this;
145 }
146 
147 QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending )
148 {
149  mOrderBy.append( OrderByClause( expression, ascending ) );
150  return *this;
151 }
152 
153 QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending, bool nullsfirst )
154 {
155  mOrderBy.append( OrderByClause( expression, ascending, nullsfirst ) );
156  return *this;
157 }
158 
160 {
161  return mOrderBy;
162 }
163 
165 {
166  mOrderBy = orderBy;
167  return *this;
168 }
169 
171 {
172  mLimit = limit;
173  return *this;
174 }
175 
177 {
178  mFlags = flags;
179  return *this;
180 }
181 
183 {
185  mAttrs = attrs;
186  return *this;
187 }
188 
189 QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QStringList &attrNames, const QgsFields &fields )
190 {
191  if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
192  {
193  //attribute string list contains the all attributes flag, so we must fetch all attributes
194  return *this;
195  }
196 
198  mAttrs.clear();
199 
200  Q_FOREACH ( const QString &attrName, attrNames )
201  {
202  int attrNum = fields.lookupField( attrName );
203  if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
204  mAttrs.append( attrNum );
205  }
206 
207  return *this;
208 }
209 
210 QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QSet<QString> &attrNames, const QgsFields &fields )
211 {
212  if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
213  {
214  //attribute string list contains the all attributes flag, so we must fetch all attributes
215  return *this;
216  }
217 
219  mAttrs.clear();
220 
221  Q_FOREACH ( const QString &attrName, attrNames )
222  {
223  int attrNum = fields.lookupField( attrName );
224  if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
225  mAttrs.append( attrNum );
226  }
227 
228  return *this;
229 }
230 
232 {
234  return *this;
235 }
236 
238 {
239  if ( !mFilterRect.isNull() )
240  {
241  if ( !feature.hasGeometry() || !feature.geometry().intersects( mFilterRect ) )
242  return false;
243  }
244 
245  switch ( mFilter )
246  {
248  return true;
249 
251  return ( feature.id() == mFilterFid );
252 
254  mExpressionContext.setFeature( feature );
255  return ( mFilterExpression->evaluate( &mExpressionContext ).toBool() );
256 
258  return ( mFilterFids.contains( feature.id() ) );
259  }
260 
261  return true;
262 }
263 
264 
265 #include "qgsfeatureiterator.h"
266 #include "qgslogger.h"
267 
269 {
270  while ( !mActiveIterators.empty() )
271  {
272  QgsAbstractFeatureIterator *it = *mActiveIterators.begin();
273  QgsDebugMsg( "closing active iterator" );
274  it->close();
275  }
276 }
277 
279 {
280  mActiveIterators.insert( it );
281 }
282 
284 {
285  mActiveIterators.remove( it );
286 }
287 
288 
289 
290 QgsFeatureRequest::OrderByClause::OrderByClause( const QString &expression, bool ascending )
291  : mExpression( expression )
292  , mAscending( ascending )
293 {
294  // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
295  mNullsFirst = !ascending;
296 }
297 
299  : mExpression( expression )
300  , mAscending( ascending )
301  , mNullsFirst( nullsfirst )
302 {
303 }
304 
306  : mExpression( expression )
307  , mAscending( ascending )
308 {
309  // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
310  mNullsFirst = !ascending;
311 }
312 
313 QgsFeatureRequest::OrderByClause::OrderByClause( const QgsExpression &expression, bool ascending, bool nullsfirst )
314  : mExpression( expression )
315  , mAscending( ascending )
316  , mNullsFirst( nullsfirst )
317 {
318 
319 }
320 
322 {
323  return mAscending;
324 }
325 
327 {
328  mAscending = ascending;
329 }
330 
332 {
333  return mNullsFirst;
334 }
335 
337 {
338  mNullsFirst = nullsFirst;
339 }
340 
342 {
343  return QStringLiteral( "%1 %2 %3" )
344  .arg( mExpression.expression(),
345  mAscending ? "ASC" : "DESC",
346  mNullsFirst ? "NULLS FIRST" : "NULLS LAST" );
347 }
348 
350 {
351  return mExpression;
352 }
353 
355 {
356  return mExpression.prepare( context );
357 }
358 
359 QgsFeatureRequest::OrderBy::OrderBy( const QList<QgsFeatureRequest::OrderByClause> &other )
360 {
361  Q_FOREACH ( const QgsFeatureRequest::OrderByClause &clause, other )
362  {
363  append( clause );
364  }
365 }
366 
367 QList<QgsFeatureRequest::OrderByClause> QgsFeatureRequest::OrderBy::list() const
368 {
369  return *this;
370 }
371 
372 void QgsFeatureRequest::OrderBy::save( QDomElement &elem ) const
373 {
374  QDomDocument doc = elem.ownerDocument();
375  QList<OrderByClause>::ConstIterator it;
376  for ( it = constBegin(); it != constEnd(); ++it )
377  {
378  const OrderByClause &clause = *it;
379  QDomElement clauseElem = doc.createElement( QStringLiteral( "orderByClause" ) );
380  clauseElem.setAttribute( QStringLiteral( "asc" ), clause.ascending() );
381  clauseElem.setAttribute( QStringLiteral( "nullsFirst" ), clause.nullsFirst() );
382  clauseElem.appendChild( doc.createTextNode( clause.expression().expression() ) );
383 
384  elem.appendChild( clauseElem );
385  }
386 }
387 
388 void QgsFeatureRequest::OrderBy::load( const QDomElement &elem )
389 {
390  clear();
391 
392  QDomNodeList clauses = elem.childNodes();
393 
394  for ( int i = 0; i < clauses.size(); ++i )
395  {
396  QDomElement clauseElem = clauses.at( i ).toElement();
397  QString expression = clauseElem.text();
398  bool asc = clauseElem.attribute( QStringLiteral( "asc" ) ).toInt() != 0;
399  bool nullsFirst = clauseElem.attribute( QStringLiteral( "nullsFirst" ) ).toInt() != 0;
400 
401  append( OrderByClause( expression, asc, nullsFirst ) );
402  }
403 }
404 
406 {
407  QSet<QString> usedAttributes;
408 
409  QList<OrderByClause>::ConstIterator it;
410  for ( it = constBegin(); it != constEnd(); ++it )
411  {
412  const OrderByClause &clause = *it;
413 
414  usedAttributes.unite( clause.expression().referencedColumns() );
415  }
416 
417  return usedAttributes;
418 }
419 
421 {
422  QStringList results;
423 
424  QList<OrderByClause>::ConstIterator it;
425  for ( it = constBegin(); it != constEnd(); ++it )
426  {
427  const OrderByClause &clause = *it;
428 
429  results << clause.dump();
430  }
431 
432  return results.join( QStringLiteral( ", " ) );
433 }
int lookupField(const QString &fieldName) const
Look up field&#39;s index from the field name.
Definition: qgsfields.cpp:289
QgsFeatureId id
Definition: qgsfeature.h:70
QgsFeatureIds mFilterFids
virtual bool close()=0
end of iterating: free the resources / lock
A rectangle specified with double values.
Definition: qgsrectangle.h:38
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
bool intersects(const QgsRectangle &r) const
Test 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:519
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Container of fields for a vector layer.
Definition: qgsfields.h:41
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:61
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
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)
QgsGeometry geometry() const
Returns the geometry associated with this feature.
Definition: qgsfeature.cpp:101
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.
void setAscending(bool ascending)
Set if ascending order is requested.
QgsAttributeList mAttrs
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.
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
QgsFeatureRequest & setInvalidGeometryCallback(std::function< void(const QgsFeature &) > callback)
Sets a callback function to use when encountering an invalid geometry and invalidGeometryCheck() is s...
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.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rect)
Set rectangle from which features will be taken.
CORE_EXPORT OrderBy()
Create a new empty order by.
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.