QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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;
88  mTimeout = rh.mTimeout;
90  return *this;
91 }
92 
94 {
95  mFilterRect = rect;
96  return *this;
97 }
98 
100 {
101  mFilter = FilterFid;
102  mFilterFid = fid;
103  return *this;
104 }
105 
107 {
109  mFilterFids = fids;
110  return *this;
111 }
112 
114 {
115  mInvalidGeometryFilter = check;
116  return *this;
117 }
118 
119 QgsFeatureRequest &QgsFeatureRequest::setInvalidGeometryCallback( const std::function<void ( const QgsFeature & )> &callback )
120 {
121  mInvalidGeometryCallback = callback;
122  return *this;
123 }
124 
126 {
128  mFilterExpression.reset( new QgsExpression( expression ) );
129  return *this;
130 }
131 
133 {
134  if ( mFilterExpression )
135  {
136  setFilterExpression( QStringLiteral( "(%1) AND (%2)" ).arg( mFilterExpression->expression(), expression ) );
137  }
138  else
139  {
140  setFilterExpression( expression );
141  }
142  return *this;
143 }
144 
146 {
147  mExpressionContext = context;
148  return *this;
149 }
150 
151 QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending )
152 {
153  mOrderBy.append( OrderByClause( expression, ascending ) );
154  return *this;
155 }
156 
157 QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending, bool nullsfirst )
158 {
159  mOrderBy.append( OrderByClause( expression, ascending, nullsfirst ) );
160  return *this;
161 }
162 
164 {
165  return mOrderBy;
166 }
167 
169 {
170  mOrderBy = orderBy;
171  return *this;
172 }
173 
175 {
176  mLimit = limit;
177  return *this;
178 }
179 
181 {
182  mFlags = flags;
183  return *this;
184 }
185 
187 {
189  mAttrs = attrs;
190  return *this;
191 }
192 
194 {
196 }
197 
198 QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QStringList &attrNames, const QgsFields &fields )
199 {
200  if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
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  const auto constAttrNames = attrNames;
210  for ( const QString &attrName : constAttrNames )
211  {
212  int attrNum = fields.lookupField( attrName );
213  if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
214  mAttrs.append( attrNum );
215  }
216 
217  return *this;
218 }
219 
220 QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QSet<QString> &attrNames, const QgsFields &fields )
221 {
222  if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
223  {
224  //attribute string list contains the all attributes flag, so we must fetch all attributes
225  return *this;
226  }
227 
229  mAttrs.clear();
230 
231  const auto constAttrNames = attrNames;
232  for ( const QString &attrName : constAttrNames )
233  {
234  int attrNum = fields.lookupField( attrName );
235  if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
236  mAttrs.append( attrNum );
237  }
238 
239  return *this;
240 }
241 
243 {
245  return *this;
246 }
247 
248 
250 {
251  return mCrs;
252 }
253 
255 {
256  return mTransformContext;
257 }
258 
260 {
261  mCrs = crs;
262  mTransformContext = context;
263  return *this;
264 }
265 
266 QgsFeatureRequest &QgsFeatureRequest::setTransformErrorCallback( const std::function<void ( const QgsFeature & )> &callback )
267 {
268  mTransformErrorCallback = callback;
269  return *this;
270 }
271 
273 {
274  if ( !mFilterRect.isNull() )
275  {
276  if ( !feature.hasGeometry() ||
277  (
278  ( mFlags & ExactIntersect && !feature.geometry().intersects( mFilterRect ) )
279  ||
281  )
282  )
283  return false;
284  }
285 
286  switch ( mFilter )
287  {
289  return true;
290 
292  return ( feature.id() == mFilterFid );
293 
295  mExpressionContext.setFeature( feature );
296  return ( mFilterExpression->evaluate( &mExpressionContext ).toBool() );
297 
299  return ( mFilterFids.contains( feature.id() ) );
300  }
301 
302  return true;
303 }
304 
306 {
307  return mTimeout;
308 }
309 
311 {
313  return *this;
314 }
315 
317 {
318  return mTimeout;
319 }
320 
322 {
323  mTimeout = timeout;
324  return *this;
325 }
326 
328 {
329  return mRequestMayBeNested;
330 }
331 
333 {
335  return *this;
336 }
337 
338 
339 #include "qgsfeatureiterator.h"
340 #include "qgslogger.h"
341 
343 {
344  while ( !mActiveIterators.empty() )
345  {
346  QgsAbstractFeatureIterator *it = *mActiveIterators.begin();
347  QgsDebugMsg( QStringLiteral( "closing active iterator" ) );
348  it->close();
349  }
350 }
351 
353 {
354  mActiveIterators.insert( it );
355 }
356 
358 {
359  mActiveIterators.remove( it );
360 }
361 
362 
363 
364 QgsFeatureRequest::OrderByClause::OrderByClause( const QString &expression, bool ascending )
365  : mExpression( expression )
366  , mAscending( ascending )
367 {
368  // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
369  mNullsFirst = !ascending;
370 }
371 
373  : mExpression( expression )
374  , mAscending( ascending )
375  , mNullsFirst( nullsfirst )
376 {
377 }
378 
380  : mExpression( expression )
381  , mAscending( ascending )
382 {
383  // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
384  mNullsFirst = !ascending;
385 }
386 
388  : mExpression( expression )
389  , mAscending( ascending )
390  , mNullsFirst( nullsfirst )
391 {
392 
393 }
394 
396 {
397  return mAscending;
398 }
399 
401 {
402  mAscending = ascending;
403 }
404 
406 {
407  return mNullsFirst;
408 }
409 
411 {
412  mNullsFirst = nullsFirst;
413 }
414 
416 {
417  return QStringLiteral( "%1 %2 %3" )
418  .arg( mExpression.expression(),
419  mAscending ? "ASC" : "DESC",
420  mNullsFirst ? "NULLS FIRST" : "NULLS LAST" );
421 }
422 
424 {
425  return mExpression;
426 }
427 
429 {
430  return mExpression.prepare( context );
431 }
432 
434 
435 QgsFeatureRequest::OrderBy::OrderBy( const QList<QgsFeatureRequest::OrderByClause> &other )
436 {
437  const auto constOther = other;
438  for ( const QgsFeatureRequest::OrderByClause &clause : constOther )
439  {
440  append( clause );
441  }
442 }
443 
444 QList<QgsFeatureRequest::OrderByClause> QgsFeatureRequest::OrderBy::list() const
445 {
446  return *this;
447 }
448 
449 void QgsFeatureRequest::OrderBy::save( QDomElement &elem ) const
450 {
451  QDomDocument doc = elem.ownerDocument();
452  QList<OrderByClause>::ConstIterator it;
453  for ( it = constBegin(); it != constEnd(); ++it )
454  {
455  const OrderByClause &clause = *it;
456  QDomElement clauseElem = doc.createElement( QStringLiteral( "orderByClause" ) );
457  clauseElem.setAttribute( QStringLiteral( "asc" ), clause.ascending() );
458  clauseElem.setAttribute( QStringLiteral( "nullsFirst" ), clause.nullsFirst() );
459  clauseElem.appendChild( doc.createTextNode( clause.expression().expression() ) );
460 
461  elem.appendChild( clauseElem );
462  }
463 }
464 
465 void QgsFeatureRequest::OrderBy::load( const QDomElement &elem )
466 {
467  clear();
468 
469  QDomNodeList clauses = elem.childNodes();
470 
471  for ( int i = 0; i < clauses.size(); ++i )
472  {
473  QDomElement clauseElem = clauses.at( i ).toElement();
474  QString expression = clauseElem.text();
475  bool asc = clauseElem.attribute( QStringLiteral( "asc" ) ).toInt() != 0;
476  bool nullsFirst = clauseElem.attribute( QStringLiteral( "nullsFirst" ) ).toInt() != 0;
477 
478  append( OrderByClause( expression, asc, nullsFirst ) );
479  }
480 }
481 
483 {
484  QSet<QString> usedAttributes;
485 
486  QList<OrderByClause>::ConstIterator it;
487  for ( it = constBegin(); it != constEnd(); ++it )
488  {
489  const OrderByClause &clause = *it;
490 
491  usedAttributes.unite( clause.expression().referencedColumns() );
492  }
493 
494  return usedAttributes;
495 }
496 
498 {
499  QSet<int> usedAttributeIdx;
500  for ( const OrderByClause &clause : *this )
501  {
502  const auto referencedColumns = clause.expression().referencedColumns();
503  for ( const QString &fieldName : referencedColumns )
504  {
505  int idx = fields.lookupField( fieldName );
506  if ( idx >= 0 )
507  {
508  usedAttributeIdx.insert( idx );
509  }
510  }
511  }
512  return usedAttributeIdx;
513 }
514 
516 {
517  QStringList results;
518 
519  QList<OrderByClause>::ConstIterator it;
520  for ( it = constBegin(); it != constEnd(); ++it )
521  {
522  const OrderByClause &clause = *it;
523 
524  results << clause.dump();
525  }
526 
527  return results.join( QStringLiteral( ", " ) );
528 }
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.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
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.
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.
QgsCoordinateTransformContext mTransformContext
std::function< void(const QgsFeature &) > mTransformErrorCallback
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:436
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:27
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.