1 /***************************************************************************
2     qgsvectorlayerfeatureiterator.h
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  ***************************************************************************/
15 #ifndef QGSVECTORLAYERFEATUREITERATOR_H
16 #define QGSVECTORLAYERFEATUREITERATOR_H
17 
18 #include "qgis_core.h"
19 #include "qgis_sip.h"
20 #include "qgsfeatureiterator.h"
21 #include "qgsfields.h"
22 #include "qgscoordinatereferencesystem.h"
23 #include "qgsfeaturesource.h"
24 #include "qgsexpressioncontextscopegenerator.h"
25 
26 #include <QPointer>
27 #include <QSet>
28 #include <memory>
29 
30 typedef QMap<QgsFeatureId, QgsFeature> QgsFeatureMap SIP_SKIP;
31 
32 class QgsExpressionFieldBuffer;
33 class QgsVectorLayer;
34 class QgsVectorLayerEditBuffer;
35 class QgsVectorLayerJoinBuffer;
36 class QgsVectorLayerJoinInfo;
37 class QgsExpressionContext;
38 
39 class QgsVectorLayerFeatureIterator;
40 
41 #ifdef SIP_RUN
42 % ModuleHeaderCode
43 #include "qgsfeatureiterator.h"
44 % End
45 #endif
46 
47 /**
48  * \ingroup core
49  * \brief Partial snapshot of vector layer's state (only the members necessary for access to features)
50 */
51 class CORE_EXPORT QgsVectorLayerFeatureSource : public QgsAbstractFeatureSource
52 {
53   public:
54 
55     /**
56      * Constructor for QgsVectorLayerFeatureSource.
57      * \param layer source layer
58      */
59     explicit QgsVectorLayerFeatureSource( const QgsVectorLayer *layer );
60 
61     //! QgsVectorLayerFeatureSource cannot be copied
62     QgsVectorLayerFeatureSource( const QgsVectorLayerFeatureSource &other ) = delete;
63     //! QgsVectorLayerFeatureSource cannot be copied
64     QgsVectorLayerFeatureSource &operator==( const QgsVectorLayerFeatureSource &other ) = delete;
65 
66     ~QgsVectorLayerFeatureSource() override;
67 
68     QgsFeatureIterator getFeatures( const QgsFeatureRequest &request = QgsFeatureRequest() ) override;
69 
70     friend class QgsVectorLayerFeatureIterator SIP_SKIP;
71 
72     /**
73      * Returns the fields that will be available for features that are retrieved from
74      * this source.
75      *
76      * \since QGIS 3.0
77      */
78     QgsFields fields() const;
79 
80     /**
81      * Returns the coordinate reference system for features retrieved from this source.
82      * \since QGIS 3.0
83      */
84     QgsCoordinateReferenceSystem crs() const;
85 
86     /**
87      * Returns the layer id of the source layer.
88      *
89      * \since QGIS 3.4
90      */
91     QString id() const;
92 
93   protected:
94 
95     std::unique_ptr< QgsAbstractFeatureSource > mProviderFeatureSource;
96     std::unique_ptr< QgsVectorLayerJoinBuffer > mJoinBuffer;
97     std::unique_ptr< QgsExpressionFieldBuffer > mExpressionFieldBuffer;
98 
99     QgsFields mFields;
100 
101     QString mId;
102 
103     QgsExpressionContextScope mLayerScope;
104 
105     bool mHasEditBuffer;
106 
107     // A deep-copy is only performed, if the original maps change
108     // see here https://github.com/qgis/Quantum-GIS/pull/673
109     // for explanation
110     QgsFeatureMap mAddedFeatures;
111     QgsGeometryMap mChangedGeometries;
112     QgsFeatureIds mDeletedFeatureIds;
113     QList<QgsField> mAddedAttributes;
114     QgsChangedAttributesMap mChangedAttributeValues;
115     QgsAttributeList mDeletedAttributeIds;
116 
117     QgsCoordinateReferenceSystem mCrs;
118 
119   private:
120 #ifdef SIP_RUN
121     QgsVectorLayerFeatureSource( const QgsVectorLayerFeatureSource &other );
122 #endif
123 };
124 
125 /**
126  * \ingroup core
127  */
128 class CORE_EXPORT QgsVectorLayerFeatureIterator : public QgsAbstractFeatureIteratorFromSource<QgsVectorLayerFeatureSource>
129 {
130   public:
131     QgsVectorLayerFeatureIterator( QgsVectorLayerFeatureSource *source, bool ownSource, const QgsFeatureRequest &request );
132 
133     ~QgsVectorLayerFeatureIterator() override;
134 
135     //! reset the iterator to the starting position
136     bool rewind() override;
137 
138     //! end of iterating: free the resources / lock
139     bool close() override;
140 
141     void setInterruptionChecker( QgsFeedback *interruptionChecker ) override SIP_SKIP;
142 
143     /**
144      * Join information prepared for fast attribute id mapping in QgsVectorLayerJoinBuffer::updateFeatureAttributes().
145      * Created in the select() method of QgsVectorLayerJoinBuffer for the joins that contain fetched attributes
146      */
147     struct CORE_EXPORT FetchJoinInfo
148     {
149       const QgsVectorLayerJoinInfo *joinInfo;//!< Canonical source of information about the join
150       QgsAttributeList attributes;      //!< Attributes to fetch
151       int indexOffset;                  //!< At what position the joined fields start
152 
153 #ifndef SIP_RUN
154 
155       /**
156        * Feature source for join
157        *
158        * \note Not available in Python bindings
159        * \since QGIS 3.20
160        */
161       std::shared_ptr< QgsVectorLayerFeatureSource > joinSource;
162 
163       /**
164        * Fields from joined layer.
165        *
166        * \note Not available in Python bindings
167        * \since QGIS 3.20
168        */
169       QgsFields joinLayerFields;
170 #endif
171 
172       int targetField;                  //!< Index of field (of this layer) that drives the join
173       int joinField;                    //!< Index of field (of the joined layer) must have equal value
174 
175       void addJoinedAttributesCached( QgsFeature &f, const QVariant &joinValue ) const;
176       void addJoinedAttributesDirect( QgsFeature &f, const QVariant &joinValue ) const;
177     };
178 
179     bool isValid() const override;
180 
181   protected:
182     //! fetch next feature, return TRUE on success
183     bool fetchFeature( QgsFeature &feature ) override;
184 
185     /**
186      * Overrides default method as we only need to filter features in the edit buffer
187      * while for others filtering is left to the provider implementation.
188      */
nextFeatureFilterExpression(QgsFeature & f)189     bool nextFeatureFilterExpression( QgsFeature &f ) override { return fetchFeature( f ); }
190 
191     //! Setup the simplification of geometries to fetch using the specified simplify method
192     bool prepareSimplification( const QgsSimplifyMethod &simplifyMethod ) override;
193 
194     //! \note not available in Python bindings
195     void rewindEditBuffer() SIP_SKIP;
196 
197     //! \note not available in Python bindings
198     void prepareJoin( int fieldIdx ) SIP_SKIP;
199 
200     //! \note not available in Python bindings
201     void prepareExpression( int fieldIdx ) SIP_SKIP;
202 
203     //! \note not available in Python bindings
204     void prepareFields() SIP_SKIP;
205 
206     //! \note not available in Python bindings
207     void prepareField( int fieldIdx ) SIP_SKIP;
208 
209     //! \note not available in Python bindings
210     bool fetchNextAddedFeature( QgsFeature &f ) SIP_SKIP;
211     //! \note not available in Python bindings
212     bool fetchNextChangedGeomFeature( QgsFeature &f ) SIP_SKIP;
213     //! \note not available in Python bindings
214     bool fetchNextChangedAttributeFeature( QgsFeature &f ) SIP_SKIP;
215     //! \note not available in Python bindings
216     void useAddedFeature( const QgsFeature &src, QgsFeature &f ) SIP_SKIP;
217     //! \note not available in Python bindings
218     void useChangedAttributeFeature( QgsFeatureId fid, const QgsGeometry &geom, QgsFeature &f ) SIP_SKIP;
219     //! \note not available in Python bindings
220     bool nextFeatureFid( QgsFeature &f ) SIP_SKIP;
221     //! \note not available in Python bindings
222     void addJoinedAttributes( QgsFeature &f ) SIP_SKIP;
223 
224     /**
225      * Adds attributes that don't source from the provider but are added inside QGIS
226      * Includes
227      *
228      * - Joined fields
229      * - Expression fields
230      *
231      * \param f The feature will be modified
232      * \note not available in Python bindings
233      */
234     void addVirtualAttributes( QgsFeature &f ) SIP_SKIP;
235 
236     /**
237      * Adds an expression based attribute to a feature
238      * \param f feature
239      * \param attrIndex attribute index
240      * \note not available in Python bindings
241      * \since QGIS 2.14
242      */
243     void addExpressionAttribute( QgsFeature &f, int attrIndex ) SIP_SKIP;
244 
245     /**
246      * Update feature with uncommitted attribute updates.
247      * \note not available in Python bindings
248      */
249     void updateChangedAttributes( QgsFeature &f ) SIP_SKIP;
250 
251     /**
252      * Update feature with uncommitted geometry updates.
253      * \note not available in Python bindings
254      */
255     void updateFeatureGeometry( QgsFeature &f ) SIP_SKIP;
256 
257     QgsFeatureRequest mProviderRequest;
258     QgsFeatureIterator mProviderIterator;
259     QgsFeatureRequest mChangedFeaturesRequest;
260     QgsFeatureIterator mChangedFeaturesIterator;
261 
262     QgsRectangle mFilterRect;
263     QgsCoordinateTransform mTransform;
264 
265     // only related to editing
266     QSet<QgsFeatureId> mFetchConsidered;
267     QgsGeometryMap::ConstIterator mFetchChangedGeomIt;
268     QgsFeatureMap::ConstIterator mFetchAddedFeaturesIt;
269 
270     bool mFetchedFid; // when iterating by FID: indicator whether it has been fetched yet or not
271 
272     /**
273      * Information about joins used in the current select() statement.
274      * Allows faster mapping of attribute ids compared to mVectorJoins.
275     */
276     QMap<const QgsVectorLayerJoinInfo *, QgsVectorLayerFeatureIterator::FetchJoinInfo> mFetchJoinInfo;
277 
278     QMap<int, QgsExpression *> mExpressionFieldInfo;
279 
280     bool mHasVirtualAttributes;
281 
282   private:
283 #ifdef SIP_RUN
284     QgsVectorLayerFeatureIterator( const QgsVectorLayerFeatureIterator &rhs );
285 #endif
286 
287     void createExpressionContext();
288     std::unique_ptr<QgsExpressionContext> mExpressionContext;
289 
290     QgsFeedback *mInterruptionChecker = nullptr;
291 
292     QList< int > mPreparedFields;
293     QList< int > mFieldsToPrepare;
294 
295     //! Join list sorted by dependency
296     QList< FetchJoinInfo > mOrderedJoinInfoList;
297 
298     /**
299      * Will always return TRUE. We assume that ordering has been done on provider level already.
300      *
301      */
302     bool prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause> &orderBys ) override;
303 
304     //! returns whether the iterator supports simplify geometries on provider side
305     bool providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const override;
306 
307     void createOrderedJoinList();
308 
309     /**
310      * Performs any post-processing (such as transformation) and feature based validity checking, e.g. checking for geometry validity.
311      */
312     bool postProcessFeature( QgsFeature &feature );
313 
314     /**
315      * Checks a feature's geometry for validity, if requested in feature request.
316      */
317     bool checkGeometryValidity( const QgsFeature &feature );
318 
319     bool mDelegatedOrderByToProvider = false;
320 };
321 
322 
323 
324 /**
325  * \class QgsVectorLayerSelectedFeatureSource
326  * \ingroup core
327  * \brief QgsFeatureSource subclass for the selected features from a QgsVectorLayer.
328  * \since QGIS 3.0
329  */
330 class CORE_EXPORT QgsVectorLayerSelectedFeatureSource : public QgsFeatureSource, public QgsExpressionContextScopeGenerator
331 {
332   public:
333 
334     /**
335      * Constructor for QgsVectorLayerSelectedFeatureSource, for selected features from the specified \a layer.
336      * The currently selected feature IDs are stored, so change to the layer selection after constructing
337      * the QgsVectorLayerSelectedFeatureSource will not be reflected.
338      */
339     QgsVectorLayerSelectedFeatureSource( QgsVectorLayer *layer );
340 
341     //! QgsVectorLayerSelectedFeatureSource cannot be copied
342     QgsVectorLayerSelectedFeatureSource( const QgsVectorLayerSelectedFeatureSource &other ) = delete;
343     //! QgsVectorLayerSelectedFeatureSource cannot be copied
344     QgsVectorLayerSelectedFeatureSource &operator==( const QgsVectorLayerSelectedFeatureSource &other ) = delete;
345 
346     QgsFeatureIterator getFeatures( const QgsFeatureRequest &request = QgsFeatureRequest() ) const override;
347     QgsCoordinateReferenceSystem sourceCrs() const override;
348     QgsFields fields() const override;
349     QgsWkbTypes::Type wkbType() const override;
350     long featureCount() const override;
351     QString sourceName() const override;
352     QgsExpressionContextScope *createExpressionContextScope() const override;
353     SpatialIndexPresence hasSpatialIndex() const override;
354 
355   private:
356 
357 #ifdef SIP_RUN
358     QgsVectorLayerSelectedFeatureSource( const QgsVectorLayerSelectedFeatureSource &other );
359 #endif
360 
361     // ideally this wouldn't be mutable, but QgsVectorLayerFeatureSource has non-const getFeatures()
362     mutable QgsVectorLayerFeatureSource mSource;
363     QgsFeatureIds mSelectedFeatureIds;
364     QgsWkbTypes::Type mWkbType = QgsWkbTypes::Unknown;
365     QString mName;
366     QPointer< QgsVectorLayer > mLayer;
367 
368 };
369 
370 ///@cond PRIVATE
371 
372 #ifndef SIP_RUN
373 class QgsVectorLayerSelectedFeatureIterator : public QgsAbstractFeatureIterator
374 {
375   public:
376 
377     QgsVectorLayerSelectedFeatureIterator( const QgsFeatureIds &selectedFeatureIds,
378                                            const QgsFeatureRequest &request,
379                                            QgsVectorLayerFeatureSource &source );
380 
381     bool rewind() override;
382     bool close() override;
383 
384   protected:
385     bool fetchFeature( QgsFeature &f ) override;
386 
387   private:
388     QgsFeatureIds mSelectedFeatureIds;
389     QgsFeatureIterator mIterator;
390 
391 };
392 
393 #endif
394 
395 ///@endcond
396 
397 #endif // QGSVECTORLAYERFEATUREITERATOR_H
398