QGIS API Documentation  2.99.0-Master (e077efd)
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::AllAttributes = QStringLiteral( "#!allattributes!#" );
24 
26  : mFilter( FilterNone )
27  , mFilterFid( -1 )
28  , mFilterExpression( nullptr )
29  , mFlags( nullptr )
30  , mLimit( -1 )
31 {
32 }
33 
35  : mFilter( FilterFid )
36  , mFilterFid( fid )
37  , mFilterExpression( nullptr )
38  , mFlags( nullptr )
39  , mLimit( -1 )
40 {
41 }
42 
44  : mFilter( FilterFids )
45  , mFilterFid( -1 )
46  , mFilterFids( fids )
47  , mFilterExpression( nullptr )
48  , mFlags( nullptr )
49  , mLimit( -1 )
50 {
51 
52 }
53 
55  : mFilter( FilterRect )
56  , mFilterRect( rect )
57  , mFilterFid( -1 )
58  , mFilterExpression( nullptr )
59  , mFlags( nullptr )
60  , mLimit( -1 )
61 {
62 }
63 
66  , mFilterFid( -1 )
67  , mFilterExpression( new QgsExpression( expr ) )
68  , mExpressionContext( context )
69  , mFlags( nullptr )
70  , mLimit( -1 )
71 {
72 }
73 
75 {
76  operator=( rh );
77 }
78 
80 {
81  mFlags = rh.mFlags;
82  mFilter = rh.mFilter;
86  if ( rh.mFilterExpression )
87  {
89  }
90  else
91  {
92  mFilterExpression = nullptr;
93  }
95  mAttrs = rh.mAttrs;
97  mLimit = rh.mLimit;
98  mOrderBy = rh.mOrderBy;
99  return *this;
100 }
101 
103 {
104  delete mFilterExpression;
105 }
106 
108 {
109  if ( mFilter == FilterNone )
111  mFilterRect = rect;
112  return *this;
113 }
114 
116 {
117  mFilter = FilterFid;
118  mFilterFid = fid;
119  return *this;
120 }
121 
123 {
125  mFilterFids = fids;
126  return *this;
127 }
128 
130 {
132  delete mFilterExpression;
133  mFilterExpression = new QgsExpression( expression );
134  return *this;
135 }
136 
138 {
139  if ( mFilterExpression )
140  {
141  setFilterExpression( QStringLiteral( "(%1) AND (%2)" ).arg( mFilterExpression->expression(), expression ) );
142  }
143  else
144  {
145  setFilterExpression( expression );
146  }
147  return *this;
148 }
149 
151 {
152  mExpressionContext = context;
153  return *this;
154 }
155 
156 QgsFeatureRequest& QgsFeatureRequest::addOrderBy( const QString& expression, bool ascending )
157 {
158  mOrderBy.append( OrderByClause( expression, ascending ) );
159  return *this;
160 }
161 
162 QgsFeatureRequest& QgsFeatureRequest::addOrderBy( const QString& expression, bool ascending, bool nullsfirst )
163 {
164  mOrderBy.append( OrderByClause( expression, ascending, nullsfirst ) );
165  return *this;
166 }
167 
169 {
170  return mOrderBy;
171 }
172 
174 {
175  mOrderBy = orderBy;
176  return *this;
177 }
178 
180 {
181  mLimit = limit;
182  return *this;
183 }
184 
186 {
187  mFlags = flags;
188  return *this;
189 }
190 
192 {
194  mAttrs = attrs;
195  return *this;
196 }
197 
198 QgsFeatureRequest& QgsFeatureRequest::setSubsetOfAttributes( const QStringList& attrNames, const QgsFields& fields )
199 {
200  if ( attrNames.contains( QgsFeatureRequest::AllAttributes ) )
201  {
202  //attribute string list contains the all attributes flag, so we must fetch all attributes
203  return *this;
204  }
205 
207  mAttrs.clear();
208 
209  Q_FOREACH ( const QString& attrName, attrNames )
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::AllAttributes ) )
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  Q_FOREACH ( const QString& attrName, attrNames )
231  {
232  int attrNum = fields.lookupField( attrName );
233  if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
234  mAttrs.append( attrNum );
235  }
236 
237  return *this;
238 }
239 
241 {
243  return *this;
244 }
245 
247 {
248  switch ( mFilter )
249  {
251  return true;
252 
254  if ( feature.hasGeometry() && feature.geometry().intersects( mFilterRect ) )
255  return true;
256  else
257  return false;
258 
260  if ( feature.id() == mFilterFid )
261  return true;
262  else
263  return false;
264 
266  mExpressionContext.setFeature( feature );
267  if ( mFilterExpression->evaluate( &mExpressionContext ).toBool() )
268  return true;
269  else
270  return false;
271 
273  if ( mFilterFids.contains( feature.id() ) )
274  return true;
275  else
276  return false;
277  }
278 
279  return true;
280 }
281 
282 
283 #include "qgsfeatureiterator.h"
284 #include "qgslogger.h"
285 
287 {
288  while ( !mActiveIterators.empty() )
289  {
290  QgsAbstractFeatureIterator *it = *mActiveIterators.begin();
291  QgsDebugMsg( "closing active iterator" );
292  it->close();
293  }
294 }
295 
297 {
298  mActiveIterators.insert( it );
299 }
300 
302 {
303  mActiveIterators.remove( it );
304 }
305 
306 
307 
308 QgsFeatureRequest::OrderByClause::OrderByClause( const QString& expression, bool ascending )
309  : mExpression( expression )
310  , mAscending( ascending )
311 {
312  // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
313  mNullsFirst = !ascending;
314 }
315 
317  : mExpression( expression )
318  , mAscending( ascending )
319  , mNullsFirst( nullsfirst )
320 {
321 }
322 
324 {
325  return mAscending;
326 }
327 
329 {
330  mAscending = ascending;
331 }
332 
334 {
335  return mNullsFirst;
336 }
337 
339 {
340  mNullsFirst = nullsFirst;
341 }
342 
344 {
345  return QStringLiteral( "%1 %2 %3" )
346  .arg( mExpression.expression(),
347  mAscending ? "ASC" : "DESC",
348  mNullsFirst ? "NULLS FIRST" : "NULLS LAST" );
349 }
350 
352 {
353  return mExpression;
354 }
355 
356 QgsFeatureRequest::OrderBy::OrderBy( const QList<QgsFeatureRequest::OrderByClause>& other )
357 {
358  Q_FOREACH ( const QgsFeatureRequest::OrderByClause& clause, other )
359  {
360  append( clause );
361  }
362 }
363 
364 QList<QgsFeatureRequest::OrderByClause> QgsFeatureRequest::OrderBy::list() const
365 {
366  return *this;
367 }
368 
369 void QgsFeatureRequest::OrderBy::save( QDomElement& elem ) const
370 {
371  QDomDocument doc = elem.ownerDocument();
372  QList<OrderByClause>::ConstIterator it;
373  for ( it = constBegin(); it != constEnd(); ++it )
374  {
375  const OrderByClause& clause = *it;
376  QDomElement clauseElem = doc.createElement( QStringLiteral( "orderByClause" ) );
377  clauseElem.setAttribute( QStringLiteral( "asc" ), clause.ascending() );
378  clauseElem.setAttribute( QStringLiteral( "nullsFirst" ), clause.nullsFirst() );
379  clauseElem.appendChild( doc.createTextNode( clause.expression().expression() ) );
380 
381  elem.appendChild( clauseElem );
382  }
383 }
384 
385 void QgsFeatureRequest::OrderBy::load( const QDomElement& elem )
386 {
387  clear();
388 
389  QDomNodeList clauses = elem.childNodes();
390 
391  for ( int i = 0; i < clauses.size(); ++i )
392  {
393  QDomElement clauseElem = clauses.at( i ).toElement();
394  QString expression = clauseElem.text();
395  bool asc = clauseElem.attribute( QStringLiteral( "asc" ) ).toInt() != 0;
396  bool nullsFirst = clauseElem.attribute( QStringLiteral( "nullsFirst" ) ).toInt() != 0;
397 
398  append( OrderByClause( expression, asc, nullsFirst ) );
399  }
400 }
401 
403 {
404  QSet<QString> usedAttributes;
405 
406  QList<OrderByClause>::ConstIterator it;
407  for ( it = constBegin(); it != constEnd(); ++it )
408  {
409  const OrderByClause& clause = *it;
410 
411  usedAttributes.unite( clause.expression().referencedColumns() );
412  }
413 
414  return usedAttributes;
415 }
416 
418 {
419  QStringList results;
420 
421  QList<OrderByClause>::ConstIterator it;
422  for ( it = constBegin(); it != constEnd(); ++it )
423  {
424  const OrderByClause& clause = *it;
425 
426  results << clause.dump();
427  }
428 
429  return results.join( QStringLiteral( ", " ) );
430 }
int lookupField(const QString &fieldName) const
Look up field&#39;s index from the field name.
Definition: qgsfields.cpp:291
Class for parsing and evaluation of expressions (formerly called "search strings").
QgsFeatureId id
Definition: qgsfeature.h:139
QgsFeatureIds mFilterFids
virtual bool close()=0
end of iterating: free the resources / lock
A rectangle specified with double values.
Definition: qgsrectangle.h:35
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)
QgsExpression * mFilterExpression
bool ascending() const
Order ascending.
const Flags & flags() const
QString dump() const
Dumps the content to an SQL equivalent.
void iteratorClosed(QgsAbstractFeatureIterator *it)
QList< 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:33
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:355
QVariant evaluate()
Evaluate the feature and return the result.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Container of fields for a vector layer.
Definition: qgsfields.h:36
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.
QSet< QString > referencedColumns() const
Get 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:135
QgsFeatureRequest & operator=(const QgsFeatureRequest &rh)
Assignment operator.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:214
QgsExpressionContext mExpressionContext
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.
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
QList< int > QgsAttributeList
static const QString AllAttributes
A special attribute that if set matches all attributes.
Obsolete, will be ignored. If a filterRect is set it will be used anyway. Filter using a rectangle...
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:113
QString expression() const
Return the original, unmodified expression string.
QgsFeatureRequest & setSimplifyMethod(const QgsSimplifyMethod &simplifyMethod)
Set a simplification method for geometries that will be fetched.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
QgsFeatureId mFilterFid
QgsExpression expression() const
The expression.
No filter is applied.
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.
QgsFeatureRequest & setLimit(long limit)
Set the maximum number of features to request.
qint64 QgsFeatureId
Definition: qgsfeature.h:32
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.
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.