QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgsvectorlayerfeatureiterator.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorlayerfeatureiterator.cpp
3  ---------------------
4  begin : Dezember 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  ***************************************************************************/
16 
18 #include "qgsgeometrysimplifier.h"
19 #include "qgsmaplayerregistry.h"
20 #include "qgssimplifymethod.h"
21 #include "qgsvectordataprovider.h"
23 #include "qgsvectorlayer.h"
25 #include "qgsexpressioncontext.h"
26 #include "qgsdistancearea.h"
27 #include "qgsproject.h"
28 
30  : mCrsId( 0 )
31 {
32  QMutexLocker locker( &layer->mFeatureSourceConstructorMutex );
34  mFields = layer->fields();
35 
36  layer->createJoinCaches();
37  mJoinBuffer = layer->mJoinBuffer->clone();
38 
39  mExpressionFieldBuffer = new QgsExpressionFieldBuffer( *layer->mExpressionFieldBuffer );
40  mCrsId = layer->crs().srsid();
41 
42  mHasEditBuffer = layer->editBuffer();
43  if ( mHasEditBuffer )
44  {
45 #if 0
46  // TODO[MD]: after merge
47  if ( request.filterType() == QgsFeatureRequest::FilterFid )
48  {
49 
50  // only copy relevant parts
51  if ( L->editBuffer()->addedFeatures().contains( request.filterFid() ) )
52  mAddedFeatures.insert( request.filterFid(), L->editBuffer()->addedFeatures()[ request.filterFid()] );
53 
54  if ( L->editBuffer()->changedGeometries().contains( request.filterFid() ) )
55  mChangedGeometries.insert( request.filterFid(), L->editBuffer()->changedGeometries()[ request.filterFid()] );
56 
57  if ( L->editBuffer()->deletedFeatureIds().contains( request.filterFid() ) )
58  mDeletedFeatureIds.insert( request.filterFid() );
59 
60  if ( L->editBuffer()->changedAttributeValues().contains( request.filterFid() ) )
61  mChangedAttributeValues.insert( request.filterFid(), L->editBuffer()->changedAttributeValues()[ request.filterFid()] );
62 
63  if ( L->editBuffer()->changedAttributeValues().contains( request.filterFid() ) )
64  mChangedFeaturesRequest.setFilterFids( QgsFeatureIds() << request.filterFid() );
65  }
66  else
67  {
68 #endif
75 #if 0
76  }
77 #endif
78  }
79 }
80 
82 {
83  delete mJoinBuffer;
86 }
87 
89 {
90  // return feature iterator that does not own this source
91  return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( this, false, request ) );
92 }
93 
94 
97  , mFetchedFid( false )
98  , mInterruptionChecker( nullptr )
99 {
101  {
104 
106  {
107  //ensure that all fields required for filter expressions are prepared
108  Q_FOREACH ( const QString& field, mRequest.filterExpression()->referencedColumns() )
109  {
110  int attrIdx = mSource->mFields.fieldNameIndex( field );
111  if ( !mRequest.subsetOfAttributes().contains( attrIdx ) )
113  }
114  }
115 
116  // Required for local filtering
117  // Also requred with compiler enabled for updateAttributeValues() on fetched features.
119  mRequest.setFlags( mRequest.flags() & ~QgsFeatureRequest::NoGeometry );
120  }
121 
122  prepareFields();
123 
125 
126  // by default provider's request is the same
128 
130  {
131  // prepare list of attributes to match provider fields
132  QSet<int> providerSubset;
134  int nPendingFields = mSource->mFields.count();
135  Q_FOREACH ( int attrIndex, subset )
136  {
137  if ( attrIndex < 0 || attrIndex >= nPendingFields ) continue;
138  if ( mSource->mFields.fieldOrigin( attrIndex ) == QgsFields::OriginProvider )
139  providerSubset << mSource->mFields.fieldOriginIndex( attrIndex );
140  }
141 
142  // This is done in order to be prepared to do fallback order bys
143  // and be sure we have the required columns.
144  // TODO:
145  // It would be nicer to first check if we can compile the order by
146  // and only modify the subset if we cannot.
147  if ( !mProviderRequest.orderBy().isEmpty() )
148  {
149  Q_FOREACH ( const QString& attr, mProviderRequest.orderBy().usedAttributes() )
150  {
151  providerSubset << mSource->mFields.fieldNameIndex( attr );
152  }
153  }
154 
155  mProviderRequest.setSubsetOfAttributes( providerSubset.toList() );
156  }
157 
159  {
160  Q_FOREACH ( const QString& field, mProviderRequest.filterExpression()->referencedColumns() )
161  {
162  int idx = source->mFields.fieldNameIndex( field );
163 
164  // If there are fields in the expression which are not of origin provider, the provider will not be able to filter based on them.
165  // In this case we disable the expression filter.
166  if ( source->mFields.fieldOrigin( idx ) != QgsFields::OriginProvider )
167  {
169  // can't limit at provider side
171  }
172  }
173  }
174 
175  if ( mSource->mHasEditBuffer )
176  {
178  QgsFeatureIds changedIds;
179  QgsChangedAttributesMap::const_iterator attIt = mSource->mChangedAttributeValues.constBegin();
180  for ( ; attIt != mSource->mChangedAttributeValues.constEnd(); ++attIt )
181  {
182  changedIds << attIt.key();
183  }
185 
186  if ( mChangedFeaturesRequest.limit() > 0 )
187  {
188  int providerLimit = mProviderRequest.limit();
189 
190  // features may be deleted in buffer, so increase limit sent to provider
191  providerLimit += mSource->mDeletedFeatureIds.size();
192 
194  {
195  // attribute changes may mean some features no longer match expression, so increase limit sent to provider
196  providerLimit += mSource->mChangedAttributeValues.size();
197  }
198 
200  {
201  // geometry changes may mean some features no longer match expression or rect, so increase limit sent to provider
202  providerLimit += mSource->mChangedGeometries.size();
203  }
204 
205  mProviderRequest.setLimit( providerLimit );
206  }
207  }
208 
209  if ( request.filterType() == QgsFeatureRequest::FilterFid )
210  {
211  mFetchedFid = false;
212  }
213  else // no filter or filter by rect
214  {
215  if ( mSource->mHasEditBuffer )
216  {
218  }
219  else
220  {
222  }
223 
225  }
226 }
227 
228 
230 {
231  qDeleteAll( mExpressionFieldInfo );
232 
233  close();
234 }
235 
236 
237 
239 {
240  f.setValid( false );
241 
242  if ( mClosed )
243  return false;
244 
246  {
247  if ( mFetchedFid )
248  return false;
249  bool res = nextFeatureFid( f );
250  mFetchedFid = true;
251  return res;
252  }
253 
254  if ( !mRequest.filterRect().isNull() )
255  {
256  if ( fetchNextChangedGeomFeature( f ) )
257  return true;
258 
259  // no more changed geometries
260  }
261 
263  {
265  return true;
266 
267  // no more changed features
268  }
269 
270  while ( fetchNextAddedFeature( f ) )
271  {
272  return true;
273  }
274  // no more added features
275 
276  if ( mProviderIterator.isClosed() )
277  {
280  mProviderIterator.setInterruptionChecker( mInterruptionChecker );
281  }
282 
283  while ( mProviderIterator.nextFeature( f ) )
284  {
285  if ( mFetchConsidered.contains( f.id() ) )
286  continue;
287 
288  // TODO[MD]: just one resize of attributes
289  f.setFields( mSource->mFields );
290 
291  // update attributes
292  if ( mSource->mHasEditBuffer )
294 
295  if ( mHasVirtualAttributes )
297 
299  {
300  //filtering by expression, and couldn't do it on the provider side
303  {
304  //feature did not match filter
305  continue;
306  }
307  }
308 
309  // update geometry
310  // TODO[MK]: FilterRect check after updating the geometry
313 
314  return true;
315  }
316  // no more provider features
317 
318  close();
319  return false;
320 }
321 
322 
323 
325 {
326  if ( mClosed )
327  return false;
328 
330  {
331  mFetchedFid = false;
332  }
333  else
334  {
337  }
338 
339  return true;
340 }
341 
343 {
344  if ( mClosed )
345  return false;
346 
348 
349  iteratorClosed();
350 
351  mClosed = true;
352  return true;
353 }
354 
356 {
357  mProviderIterator.setInterruptionChecker( interruptionChecker );
358  mInterruptionChecker = interruptionChecker;
359 }
360 
362 {
364  {
366 
367  if ( mFetchConsidered.contains( fid ) )
368  // must have changed geometry outside rectangle
369  continue;
370 
372  // skip features which are not accepted by the filter
373  continue;
374 
376 
377  return true;
378  }
379 
381  return false; // no more added features
382 }
383 
384 
386 {
387  f.setFeatureId( src.id() );
388  f.setValid( true );
389  f.setFields( mSource->mFields );
390 
392  {
393  f.setGeometry( new QgsGeometry( *src.constGeometry() ) );
394  }
395 
396  // TODO[MD]: if subset set just some attributes
397 
398  f.setAttributes( src.attributes() );
399 
400  if ( mHasVirtualAttributes )
402 }
403 
404 
405 
407 {
408  // check if changed geometries are in rectangle
410  {
411  QgsFeatureId fid = mFetchChangedGeomIt.key();
412 
413  if ( mFetchConsidered.contains( fid ) )
414  // skip deleted features
415  continue;
416 
417  mFetchConsidered << fid;
418 
419  if ( !mFetchChangedGeomIt->intersects( mRequest.filterRect() ) )
420  // skip changed geometries not in rectangle and don't check again
421  continue;
422 
424 
425  // return complete feature
427  return true;
428  }
429 
430  return false; // no more changed geometries
431 }
432 
434 {
436  {
437  if ( mFetchConsidered.contains( f.id() ) )
438  // skip deleted features and those already handled by the geometry
439  continue;
440 
441  mFetchConsidered << f.id();
442 
444 
445  if ( mHasVirtualAttributes )
447 
450  {
451  return true;
452  }
453  }
454 
455  return false;
456 }
457 
458 
460 {
461  f.setFeatureId( fid );
462  f.setValid( true );
463  f.setFields( mSource->mFields );
464 
466  {
467  f.setGeometry( geom );
468  }
469 
470  bool subsetAttrs = ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes );
471  if ( !subsetAttrs || !mRequest.subsetOfAttributes().isEmpty() )
472  {
473  // retrieve attributes from provider
474  QgsFeature tmp;
475  //mDataProvider->featureAtId( fid, tmp, false, mFetchProvAttributes );
476  QgsFeatureRequest request;
478  if ( subsetAttrs )
479  {
481  }
483  if ( fi.nextFeature( tmp ) )
484  {
487  f.setAttributes( tmp.attributes() );
488  }
489  }
490 
492 }
493 
494 
495 
497 {
499 
502 }
503 
505 {
506  if ( !mSource->mFields.exists( fieldIdx ) )
507  return;
508 
509  if ( mSource->mFields.fieldOrigin( fieldIdx ) != QgsFields::OriginJoin )
510  return;
511 
512  int sourceLayerIndex;
513  const QgsVectorJoinInfo* joinInfo = mSource->mJoinBuffer->joinForFieldIndex( fieldIdx, mSource->mFields, sourceLayerIndex );
514  Q_ASSERT( joinInfo );
515 
516  QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo->joinLayerId ) );
517  Q_ASSERT( joinLayer );
518 
519  if ( !mFetchJoinInfo.contains( joinInfo ) )
520  {
521  FetchJoinInfo info;
522  info.joinInfo = joinInfo;
523  info.joinLayer = joinLayer;
525 
526  if ( joinInfo->targetFieldName.isEmpty() )
527  info.targetField = joinInfo->targetFieldIndex; //for compatibility with 1.x
528  else
530 
531  if ( joinInfo->joinFieldName.isEmpty() )
532  info.joinField = joinInfo->joinFieldIndex; //for compatibility with 1.x
533  else
534  info.joinField = joinLayer->fields().indexFromName( joinInfo->joinFieldName );
535 
536  // for joined fields, we always need to request the targetField from the provider too
537  if ( !mPreparedFields.contains( info.targetField ) && !mFieldsToPrepare.contains( info.targetField ) )
538  mFieldsToPrepare << info.targetField;
539 
542 
543  mFetchJoinInfo.insert( joinInfo, info );
544  }
545 
546  // store field source index - we'll need it when fetching from provider
547  mFetchJoinInfo[ joinInfo ].attributes.push_back( sourceLayerIndex );
548 }
549 
551 {
553 
554  int oi = mSource->mFields.fieldOriginIndex( fieldIdx );
555  QgsExpression* exp = new QgsExpression( exps[oi].cachedExpression );
556 
557  QgsDistanceArea da;
558  da.setSourceCrs( mSource->mCrsId );
559  da.setEllipsoidalMode( true );
560  da.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
561  exp->setGeomCalculator( da );
562  exp->setDistanceUnits( QgsProject::instance()->distanceUnits() );
563  exp->setAreaUnits( QgsProject::instance()->areaUnits() );
564 
565  exp->prepare( mExpressionContext.data() );
566  mExpressionFieldInfo.insert( fieldIdx, exp );
567 
568  Q_FOREACH ( const QString& col, exp->referencedColumns() )
569  {
570  int dependentFieldIdx = mSource->mFields.fieldNameIndex( col );
572  {
573  mRequest.setSubsetOfAttributes( mRequest.subsetOfAttributes() << dependentFieldIdx );
574  }
575  // also need to fetch this dependent field
576  if ( !mPreparedFields.contains( dependentFieldIdx ) && !mFieldsToPrepare.contains( dependentFieldIdx ) )
577  mFieldsToPrepare << dependentFieldIdx;
578  }
579 
580  if ( exp->needsGeometry() )
581  {
582  mRequest.setFlags( mRequest.flags() & ~QgsFeatureRequest::NoGeometry );
583  }
584 }
585 
587 {
588  mPreparedFields.clear();
589  mFieldsToPrepare.clear();
590  mFetchJoinInfo.clear();
591 
592  mExpressionContext.reset( new QgsExpressionContext() );
593  mExpressionContext->appendScope( QgsExpressionContextUtils::globalScope() );
594  mExpressionContext->appendScope( QgsExpressionContextUtils::projectScope() );
595  mExpressionContext->setFields( mSource->mFields );
596 
598 
599  while ( !mFieldsToPrepare.isEmpty() )
600  {
601  int fieldIdx = mFieldsToPrepare.takeFirst();
602  if ( mPreparedFields.contains( fieldIdx ) )
603  continue;
604 
605  mPreparedFields << fieldIdx;
606  prepareField( fieldIdx );
607  }
608 }
609 
611 {
612  switch ( mSource->mFields.fieldOrigin( fieldIdx ) )
613  {
615  prepareExpression( fieldIdx );
616  break;
617 
620  {
621  prepareJoin( fieldIdx );
622  }
623  break;
624 
628  break;
629  }
630 }
631 
633 {
635  for ( ; joinIt != mFetchJoinInfo.constEnd(); ++joinIt )
636  {
637  const FetchJoinInfo& info = joinIt.value();
638  Q_ASSERT( joinIt.key() );
639 
640  QVariant targetFieldValue = f.attribute( info.targetField );
641  if ( !targetFieldValue.isValid() )
642  continue;
643 
644  const QHash< QString, QgsAttributes>& memoryCache = info.joinInfo->cachedAttributes;
645  if ( memoryCache.isEmpty() )
646  info.addJoinedAttributesDirect( f, targetFieldValue );
647  else
648  info.addJoinedAttributesCached( f, targetFieldValue );
649  }
650 }
651 
653 {
654  // make sure we have space for newly added attributes
655  QgsAttributes attr = f.attributes();
656  attr.resize( mSource->mFields.count() ); // Provider attrs count + joined attrs count + expression attrs count
657  f.setAttributes( attr );
658 
659  // possible TODO - handle combinations of expression -> join -> expression -> join?
660  // but for now, write that off as too complex and an unlikely rare, unsupported use case
661 
662  QList< int > fetchedVirtualAttributes;
663  //first, check through joins for any virtual fields we need
665  for ( ; joinIt != mFetchJoinInfo.constEnd(); ++joinIt )
666  {
667  if ( mExpressionFieldInfo.contains( joinIt->targetField ) )
668  {
669  // have to calculate expression field before we can handle this join
670  addExpressionAttribute( f, joinIt->targetField );
671  fetchedVirtualAttributes << joinIt->targetField;
672  }
673  }
674 
675  if ( !mFetchJoinInfo.isEmpty() )
676  addJoinedAttributes( f );
677 
678  // add remaining expression fields
679  if ( !mExpressionFieldInfo.isEmpty() )
680  {
682  for ( ; it != mExpressionFieldInfo.constEnd(); ++it )
683  {
684  if ( fetchedVirtualAttributes.contains( it.key() ) )
685  continue;
686 
687  addExpressionAttribute( f, it.key() );
688  }
689  }
690 }
691 
693 {
694  QgsExpression* exp = mExpressionFieldInfo.value( attrIndex );
695  mExpressionContext->setFeature( f );
696  QVariant val = exp->evaluate( mExpressionContext.data() );
697  mSource->mFields.at( attrIndex ).convertCompatible( val );
698  f.setAttribute( attrIndex, val );
699 }
700 
702 {
703  Q_UNUSED( simplifyMethod );
704  return false;
705 }
706 
707 bool QgsVectorLayerFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const
708 {
709  Q_UNUSED( methodType );
710  return false;
711 }
712 
713 
715 {
716  const QHash<QString, QgsAttributes>& memoryCache = joinInfo->cachedAttributes;
717  QHash<QString, QgsAttributes>::const_iterator it = memoryCache.find( joinValue.toString() );
718  if ( it == memoryCache.constEnd() )
719  return; // joined value not found -> leaving the attributes empty (null)
720 
721  int index = indexOffset;
722 
723  const QgsAttributes& featureAttributes = it.value();
724  for ( int i = 0; i < featureAttributes.count(); ++i )
725  {
726  f.setAttribute( index++, featureAttributes.at( i ) );
727  }
728 }
729 
730 
731 
733 {
734  // no memory cache, query the joined values by setting substring
735  QString subsetString;
736 
737  QString joinFieldName;
738  if ( joinInfo->joinFieldName.isEmpty() && joinInfo->joinFieldIndex >= 0 && joinInfo->joinFieldIndex < joinLayer->fields().count() )
739  joinFieldName = joinLayer->fields().field( joinInfo->joinFieldIndex ).name(); // for compatibility with 1.x
740  else
741  joinFieldName = joinInfo->joinFieldName;
742 
743  subsetString.append( QString( "\"%1\"" ).arg( joinFieldName ) );
744 
745  if ( joinValue.isNull() )
746  {
747  subsetString += " IS NULL";
748  }
749  else
750  {
751  QString v = joinValue.toString();
752  switch ( joinValue.type() )
753  {
754  case QVariant::Int:
755  case QVariant::LongLong:
756  case QVariant::Double:
757  break;
758 
759  default:
760  case QVariant::String:
761  v.replace( '\'', "''" );
762  v.prepend( '\'' ).append( '\'' );
763  break;
764  }
765  subsetString += '=' + v;
766  }
767 
768  // maybe user requested just a subset of layer's attributes
769  // so we do not have to cache everything
770  bool hasSubset = joinInfo->joinFieldNamesSubset();
771  QVector<int> subsetIndices;
772  if ( hasSubset )
773  subsetIndices = QgsVectorLayerJoinBuffer::joinSubsetIndices( joinLayer, *joinInfo->joinFieldNamesSubset() );
774 
775  // select (no geometry)
776  QgsFeatureRequest request;
778  request.setSubsetOfAttributes( attributes );
779  request.setFilterExpression( subsetString );
780  request.setLimit( 1 );
781  QgsFeatureIterator fi = joinLayer->getFeatures( request );
782 
783  // get first feature
784  QgsFeature fet;
785  if ( fi.nextFeature( fet ) )
786  {
787  int index = indexOffset;
788  QgsAttributes attr = fet.attributes();
789  if ( hasSubset )
790  {
791  for ( int i = 0; i < subsetIndices.count(); ++i )
792  f.setAttribute( index++, attr.at( subsetIndices.at( i ) ) );
793  }
794  else
795  {
796  // use all fields except for the one used for join (has same value as exiting field in target layer)
797  for ( int i = 0; i < attr.count(); ++i )
798  {
799  if ( i == joinField )
800  continue;
801 
802  f.setAttribute( index++, attr.at( i ) );
803  }
804  }
805  }
806  else
807  {
808  // no suitable join feature found, keeping empty (null) attributes
809  }
810 }
811 
812 
813 
814 
816 {
817  QgsFeatureId featureId = mRequest.filterFid();
818 
819  // deleted already?
820  if ( mSource->mDeletedFeatureIds.contains( featureId ) )
821  return false;
822 
823  // has changed geometry?
825  {
826  useChangedAttributeFeature( featureId, mSource->mChangedGeometries[featureId], f );
827  return true;
828  }
829 
830  // added features
832  {
833  if ( iter->id() == featureId )
834  {
835  useAddedFeature( *iter, f );
836  return true;
837  }
838  }
839 
840  // regular features
842  if ( fi.nextFeature( f ) )
843  {
844  f.setFields( mSource->mFields );
845 
846  if ( mSource->mHasEditBuffer )
848 
849  if ( mHasVirtualAttributes )
851 
852  return true;
853  }
854 
855  return false;
856 }
857 
859 {
860  QgsAttributes attrs = f.attributes();
861 
862  // remove all attributes that will disappear - from higher indices to lower
863  for ( int idx = mSource->mDeletedAttributeIds.count() - 1; idx >= 0; --idx )
864  {
865  attrs.remove( mSource->mDeletedAttributeIds[idx] );
866  }
867 
868  // adjust size to accommodate added attributes
869  attrs.resize( attrs.count() + mSource->mAddedAttributes.count() );
870 
871  // update changed attributes
873  {
875  for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); ++it )
876  attrs[it.key()] = it.value();
877  }
878  f.setAttributes( attrs );
879 }
880 
882 {
883  if ( mSource->mChangedGeometries.contains( f.id() ) )
885 }
886 
887 bool QgsVectorLayerFeatureIterator::prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause>& orderBys )
888 {
889  Q_UNUSED( orderBys );
890  return true;
891 }
892 
void setAreaUnits(QgsUnitTypes::AreaUnit unit)
Sets the desired areal units for calculations involving geomCalculator(), eg "$area".
const QgsGeometryMap & changedGeometries()
Changed geometries which are not commited.
QgsAbstractFeatureSource * mProviderFeatureSource
Class for parsing and evaluation of expressions (formerly called "search strings").
void clear()
void addJoinedAttributesDirect(QgsFeature &f, const QVariant &joinValue) const
Wrapper for iterator of features from vector data provider or vector layer.
QMap< QgsFeatureId, QgsGeometry > QgsGeometryMap
Definition: qgsfeature.h:437
static unsigned index
long limit() const
Returns the maximum number of features to request, or -1 if no limit set.
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.
QString & append(QChar ch)
Filter using feature ID.
QgsVectorLayerJoinBuffer * mJoinBuffer
bool containsJoins() const
Quick way to test if there is any join at all.
QString joinFieldName
Join field in the source layer.
field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
Definition: qgsfield.h:260
QgsAttributes attributes() const
Returns the feature&#39;s attributes.
Definition: qgsfeature.cpp:110
virtual void setInterruptionChecker(QgsInterruptionChecker *interruptionChecker) override
Attach an object that can be queried regularly by the iterator to check if it must stopped...
FieldOrigin fieldOrigin(int fieldIdx) const
Get field&#39;s origin (value from an enumeration)
Definition: qgsfield.cpp:448
QString targetFieldName
Join field in the target layer.
bool contains(const Key &key) const
Q_DECL_DEPRECATED QVariant evaluate(const QgsFeature *f)
Evaluate the feature and return the result.
const Flags & flags() const
void addExpressionAttribute(QgsFeature &f, int attrIndex)
Adds an expression based attribute to a feature.
QgsFeatureMap::ConstIterator mFetchAddedFeaturesIt
QgsGeometryMap::ConstIterator mFetchChangedGeomIt
Q_DECL_DEPRECATED bool prepare(const QgsFields &fields)
Get the expression ready for evaluation - find out column indexes.
field has been temporarily added in editing mode (originIndex = index in the list of added attributes...
Definition: qgsfield.h:261
bool exists(int i) const
Return if a field index is valid.
Definition: qgsfield.cpp:412
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:439
int size() const
QgsMapLayer * mapLayer(const QString &theLayerId) const
Retrieve a pointer to a registered layer by layer ID.
QStringList referencedColumns() const
Get list of columns referenced by the expression.
QString & prepend(QChar ch)
void setSourceCrs(long srsid)
sets source spatial reference system (by QGIS CRS)
QgsVectorLayerFeatureIterator(QgsVectorLayerFeatureSource *source, bool ownSource, const QgsFeatureRequest &request)
QgsExpressionContext * expressionContext()
Returns the expression context used to evaluate filter expressions.
int joinFieldIndex
Join field index in the source layer.
const QgsVectorJoinInfo * joinForFieldIndex(int index, const QgsFields &fields, int &sourceFieldIndex) const
Finds the vector join for a layer field index.
const_iterator constBegin() const
QgsFeatureId filterFid() const
Get the feature ID that should be fetched.
const QgsCoordinateReferenceSystem & crs() const
Returns layer&#39;s spatial reference system.
const QgsChangedAttributesMap & changedAttributeValues()
Changed attributes values which are not commited.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
bool convertCompatible(QVariant &v) const
Converts the provided variant to a compatible format.
Definition: qgsfield.cpp:208
FilterType filterType() const
Return the filter type which is currently set on this request.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
void setAttributes(const QgsAttributes &attrs)
Sets the feature&#39;s attributes.
Definition: qgsfeature.cpp:115
bool setAttribute(int field, const QVariant &attr)
Set an attribute&#39;s value by field index.
Definition: qgsfeature.cpp:222
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QMap< int, QgsExpression * > mExpressionFieldInfo
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
field comes from the underlying data provider of the vector layer (originIndex = index in provider&#39;s ...
Definition: qgsfield.h:259
bool setEllipsoid(const QString &ellipsoid)
Sets ellipsoid by its acronym.
bool mClosed
Set to true, as soon as the iterator is closed.
int targetFieldIndex
Join field index in the target layer.
const_iterator insert(const T &value)
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
QgsVectorLayer * joinLayer
resolved pointer to the joined layer
const QgsRectangle & filterRect() const
Get the rectangle from which features will be taken.
int count() const
Return number of items.
Definition: qgsfield.cpp:402
const QList< ExpressionField > & expressions() const
it has not been specified where the field comes from
Definition: qgsfield.h:258
const QString GEO_NONE
Constant that holds the string representation for "No ellips/No CRS".
Definition: qgis.cpp:76
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:422
QMap< const QgsVectorJoinInfo *, FetchJoinInfo > mFetchJoinInfo
Information about joins used in the current select() statement.
void reset(T *other)
T value(int i) const
QgsFields fields() const
Returns the list of fields of this layer.
int joinedFieldsOffset(const QgsVectorJoinInfo *info, const QgsFields &fields)
Find out what is the first index of the join within fields.
int joinField
index of field (of the joined layer) must have equal value
QgsExpression * filterExpression() const
Returns the filter expression if set.
int fieldOriginIndex(int fieldIdx) const
Get field&#39;s origin index (its meaning is specific to each type of origin)
Definition: qgsfield.cpp:456
virtual QgsAbstractFeatureSource * featureSource() const =0
Return feature source object that can be used for querying provider&#39;s data.
Interface that can be optionaly attached to an iterator so its nextFeature() implementaton can check ...
void updateChangedAttributes(QgsFeature &f)
Update feature with uncommited attribute updates.
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Set feature ID that should be fetched.
void setGeometry(const QgsGeometry &geom)
Set this feature&#39;s geometry from another QgsGeometry object.
Definition: qgsfeature.cpp:124
QgsVectorLayerEditBuffer * editBuffer()
Buffer with uncommitted editing operations. Only valid after editing has been turned on...
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
int count(const T &value) const
void iteratorClosed()
to be called by from subclass in close()
void useAddedFeature(const QgsFeature &src, QgsFeature &f)
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
void resize(int size)
const_iterator constEnd() const
void setFeatureId(QgsFeatureId id)
Sets the feature ID for this feature.
Definition: qgsfeature.cpp:101
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
Definition: qgsfield.cpp:588
bool isNull() const
const Key & key() const
const QgsVectorJoinInfo * joinInfo
cannonical source of information about the join
QgsFeatureRequest & disableFilter()
Disables filter conditions.
void updateFeatureGeometry(QgsFeature &f)
Update feature with uncommited geometry updates.
bool isEmpty() const
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
virtual bool prepareSimplification(const QgsSimplifyMethod &simplifyMethod) override
Setup the simplification of geometries to fetch using the specified simplify method.
void addJoinedAttributesCached(QgsFeature &f, const QVariant &joinValue) const
bool isEmpty() const
const_iterator constEnd() const
void remove(int i)
virtual bool fetchFeature(QgsFeature &feature) override
fetch next feature, return true on success
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QList< int > QgsAttributeList
const QgsFeatureIds deletedFeatureIds()
const T & value() const
Obsolete, will be ignored. If a filterRect is set it will be used anyway. Filter using a rectangle...
QgsFeatureRequest & setFlags(const QgsFeatureRequest::Flags &flags)
Set flags that affect how features will be fetched.
iterator end()
Fetch only a subset of attributes (setSubsetOfAttributes sets this flag)
QgsExpressionFieldBuffer * mExpressionFieldBuffer
iterator begin()
Q_DECL_DEPRECATED void setFields(const QgsFields *fields, bool initAttributes=false)
Assign a field map with the feature to allow attribute access by attribute name.
Definition: qgsfeature.cpp:173
const QList< QgsField > & addedAttributes()
Added attributes fields which are not commited.
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the context.
T * data() const
const T value(const Key &key) const
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:65
QgsAttributeList subsetOfAttributes() const
Return the subset of attributes which at least need to be fetched.
iterator find(const Key &key)
int fieldNameIndex(const QString &fieldName) const
Look up field&#39;s index from name also looks up case-insensitive if there is no match otherwise...
Definition: qgsfield.cpp:571
Partial snapshot of vector layer&#39;s state (only the members necessary for access to features) ...
bool contains(const T &value) const
QgsVectorLayerFeatureSource(QgsVectorLayer *layer)
bool contains(const T &value) const
int indexOffset
at what position the joined fields start
void useChangedAttributeFeature(QgsFeatureId fid, const QgsGeometry &geom, QgsFeature &f)
const QgsFeatureMap & addedFeatures()
New features which are not commited.
const Key key(const T &value) const
General purpose distance and area calculator.
void setValid(bool validity)
Sets the validity of the feature.
Definition: qgsfeature.cpp:204
QMap< QgsFeatureId, QgsFeature > QgsFeatureMap
QString & replace(int position, int n, QChar after)
QgsFeatureRequest mRequest
A copy of the feature request.
const T & at(int i) const
int targetField
index of field (of this layer) that drives the join
int indexFromName(const QString &name) const
Look up field&#39;s index from name. Returns -1 on error.
Definition: qgsfield.cpp:461
Buffers information about expression fields for a vector layer.
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QHash< QString, QgsAttributes > cachedAttributes
Cache for joined attributes to provide fast lookup (size is 0 if no memory caching) ...
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Set feature IDs that should be fetched.
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request) override
Get an iterator for features matching the specified request.
QMap< QgsFeatureId, QgsAttributeMap > QgsChangedAttributesMap
Definition: qgsfeature.h:434
T takeFirst()
bool isEmpty() const
virtual bool rewind() override
reset the iterator to the starting position
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:382
virtual bool close() override
end of iterating: free the resources / lock
static QVector< int > joinSubsetIndices(QgsVectorLayer *joinLayer, const QStringList &joinFieldsSubset)
Return a vector of indices for use in join based on field names from the layer.
int count(const T &value) const
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
void setDistanceUnits(QGis::UnitType unit)
Sets the desired distance units for calculations involving geomCalculator(), eg "$length" and "$perim...
QgsFeatureRequest & setLimit(long limit)
Set the maximum number of features to request.
Join information prepared for fast attribute id mapping in QgsVectorLayerJoinBuffer::updateFeatureAtt...
qint64 QgsFeatureId
Definition: qgsfeature.h:31
void setGeomCalculator(const QgsDistanceArea &calc)
Sets the geometry calculator used for distance and area calculations in expressions.
QList< T > toList() const
This class contains information about how to simplify geometries fetched from a QgsFeatureIterator.
iterator insert(const Key &key, const T &value)
bool isEmpty() const
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request)=0
Get an iterator for features matching the specified request.
QgsVectorDataProvider * dataProvider()
Returns the data provider.
bool nextFeature(QgsFeature &f)
long srsid() const
Returns the SrsId, if available.
Type type() const
QgsChangedAttributesMap mChangedAttributeValues
OrderBy orderBy() const
Return a list of order by clauses specified for this feature request.
Geometry is not required. It may still be returned if e.g. required for a filter condition.
A vector of attributes.
Definition: qgsfeature.h:115
Represents a vector layer which manages a vector based data sets.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:271
const QgsAttributeList & deletedAttributeIds()
Deleted attributes fields which are not commited.
field is calculated from an expression
Definition: qgsfield.h:262
QString toString() const
QString joinLayerId
Source layer.
int size() const
bool isClosed() const
find out whether the iterator is still valid or closed already
void createJoinCaches()
Caches joined attributes if required (and not already done)
void setInterruptionChecker(QgsInterruptionChecker *interruptionChecker)
Attach an object that can be queried regularly by the iterator to check if it must stopped...
void setEllipsoidalMode(bool flag)
Sets whether coordinates must be projected to ellipsoid before measuring.
QgsVectorLayerJoinBuffer * clone() const
Create a copy of the join buffer.
void addVirtualAttributes(QgsFeature &f)
Adds attributes that don&#39;t source from the provider but are added inside QGIS Includes.
Helper template that cares of two things: 1.
const T value(const Key &key) const