LCOV - code coverage report
Current view: top level - core/vector - qgsvectorlayercache.h (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 18 0.0 %
Date: 2021-04-10 08:29:14 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :   qgsvectorlayercache.h
       3                 :            :   Cache features of a vector layer
       4                 :            :   -------------------
       5                 :            :          begin                : January 2013
       6                 :            :          copyright            : (C) Matthias Kuhn
       7                 :            :          email                : matthias at opengis dot ch
       8                 :            : 
       9                 :            :  ***************************************************************************
      10                 :            :  *                                                                         *
      11                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      12                 :            :  *   it under the terms of the GNU General Public License as published by  *
      13                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      14                 :            :  *   (at your option) any later version.                                   *
      15                 :            :  *                                                                         *
      16                 :            :  ***************************************************************************/
      17                 :            : 
      18                 :            : 
      19                 :            : #ifndef QgsVectorLayerCache_H
      20                 :            : #define QgsVectorLayerCache_H
      21                 :            : 
      22                 :            : #include "qgis_core.h"
      23                 :            : #include "qgis_sip.h"
      24                 :            : #include "qgsfield.h"
      25                 :            : #include "qgsfeaturerequest.h"
      26                 :            : #include "qgsfeatureiterator.h"
      27                 :            : 
      28                 :            : #include <QCache>
      29                 :            : 
      30                 :            : class QgsVectorLayer;
      31                 :            : class QgsFeature;
      32                 :            : class QgsCachedFeatureIterator;
      33                 :            : class QgsAbstractCacheIndex;
      34                 :            : 
      35                 :            : /**
      36                 :            :  * \ingroup core
      37                 :            :  * \brief This class caches features of a given QgsVectorLayer.
      38                 :            :  *
      39                 :            :  * \brief
      40                 :            :  * The cached features can be indexed by QgsAbstractCacheIndex.
      41                 :            :  *
      42                 :            :  * Proper indexing for a given use-case may speed up performance substantially.
      43                 :            :  */
      44                 :            : 
      45                 :            : class CORE_EXPORT QgsVectorLayerCache : public QObject
      46                 :            : {
      47                 :            :     Q_OBJECT
      48                 :            : 
      49                 :            :   private:
      50                 :            : 
      51                 :            :     /**
      52                 :            :      * This is a wrapper class around a cached QgsFeature, which
      53                 :            :      * will inform the cache, when it has been deleted, so indexes can be
      54                 :            :      * updated that the wrapped feature needs to be fetched again if needed.
      55                 :            :      */
      56                 :            :     class QgsCachedFeature
      57                 :            :     {
      58                 :            :       public:
      59                 :            : 
      60                 :            :         /**
      61                 :            :          * Will create a new cached feature.
      62                 :            :          *
      63                 :            :          * \param feat     The feature to cache. A copy will be made.
      64                 :            :          * \param vlCache  The cache to inform when the feature has been removed from the cache.
      65                 :            :          */
      66                 :          0 :         QgsCachedFeature( const QgsFeature &feat, QgsVectorLayerCache *vlCache )
      67                 :          0 :           : mCache( vlCache )
      68                 :            :         {
      69                 :          0 :           mFeature = new QgsFeature( feat );
      70                 :          0 :         }
      71                 :            : 
      72                 :          0 :         ~QgsCachedFeature()
      73                 :            :         {
      74                 :            :           // That's the reason we need this wrapper:
      75                 :            :           // Inform the cache that this feature has been removed
      76                 :          0 :           mCache->featureRemoved( mFeature->id() );
      77                 :          0 :           delete mFeature;
      78                 :          0 :         }
      79                 :            : 
      80                 :          0 :         inline const QgsFeature *feature() { return mFeature; }
      81                 :            : 
      82                 :            :       private:
      83                 :          0 :         QgsFeature *mFeature = nullptr;
      84                 :            :         QgsVectorLayerCache *mCache = nullptr;
      85                 :            : 
      86                 :            :         friend class QgsVectorLayerCache;
      87                 :            :         Q_DISABLE_COPY( QgsCachedFeature )
      88                 :            :     };
      89                 :            : 
      90                 :            :   public:
      91                 :            :     QgsVectorLayerCache( QgsVectorLayer *layer, int cacheSize, QObject *parent SIP_TRANSFERTHIS = nullptr );
      92                 :            :     ~QgsVectorLayerCache() override;
      93                 :            : 
      94                 :            :     /**
      95                 :            :      * Sets the maximum number of features to keep in the cache. Some features will be removed from
      96                 :            :      * the cache if the number is smaller than the previous size of the cache.
      97                 :            :      *
      98                 :            :      * \param cacheSize indicates the maximum number of features to keep in the cache
      99                 :            :      */
     100                 :            :     void setCacheSize( int cacheSize );
     101                 :            : 
     102                 :            :     /**
     103                 :            :      * \brief
     104                 :            :      * Returns the maximum number of features this cache will hold.
     105                 :            :      * In case full caching is enabled, this number can change, as new features get added.
     106                 :            :      *
     107                 :            :      * \returns int
     108                 :            :      */
     109                 :            :     int cacheSize();
     110                 :            : 
     111                 :            :     /**
     112                 :            :      * Enable or disable the caching of geometries
     113                 :            :      *
     114                 :            :      * \param cacheGeometry    Enable or disable the caching of geometries
     115                 :            :      * \see cacheGeometry()
     116                 :            :      */
     117                 :            :     void setCacheGeometry( bool cacheGeometry );
     118                 :            : 
     119                 :            :     /**
     120                 :            :      * Returns TRUE if the cache will fetch and cache feature geometries.
     121                 :            :      * \see setCacheGeometry()
     122                 :            :      * \since QGIS 3.0
     123                 :            :      */
     124                 :            :     bool cacheGeometry() const { return mCacheGeometry; }
     125                 :            : 
     126                 :            :     /**
     127                 :            :      * Set the subset of attributes to be cached
     128                 :            :      *
     129                 :            :      * \param attributes   The attributes to be cached
     130                 :            :      */
     131                 :            :     void setCacheSubsetOfAttributes( const QgsAttributeList &attributes );
     132                 :            : 
     133                 :            :     /**
     134                 :            :      * If this is enabled, the subset of cached attributes will automatically be extended
     135                 :            :      * to also include newly added attributes.
     136                 :            :      *
     137                 :            :      * \param cacheAddedAttributes   Automatically cache new attributes
     138                 :            :      */
     139                 :            :     void setCacheAddedAttributes( bool cacheAddedAttributes );
     140                 :            : 
     141                 :            :     /**
     142                 :            :      * \brief
     143                 :            :      * This enables or disables full caching.
     144                 :            :      * If enabled, all features will be held in the cache. The cache size will incrementally
     145                 :            :      * be increased to offer space for all features.
     146                 :            :      * When enabled, all features will be read into cache. As this feature will most likely
     147                 :            :      * be used for slow data sources, be aware, that the call to this method might take a long time.
     148                 :            :      *
     149                 :            :      * \param fullCache   TRUE: enable full caching, FALSE: disable full caching
     150                 :            :      * \note when a cache is invalidated() (e.g. by adding an attribute to a layer) this setting
     151                 :            :      * is reset. A full cache rebuild must be performed by calling setFullCache( TRUE ) again.
     152                 :            :      * \see hasFullCache()
     153                 :            :      */
     154                 :            :     void setFullCache( bool fullCache );
     155                 :            : 
     156                 :            :     /**
     157                 :            :      * Returns TRUE if the cache is complete, ie it contains all features. This may happen as
     158                 :            :      * a result of a call to setFullCache() or by through a feature request which resulted in
     159                 :            :      * all available features being cached.
     160                 :            :      * \see setFullCache()
     161                 :            :      * \since QGIS 3.0
     162                 :            :      */
     163                 :          0 :     bool hasFullCache() const { return mFullCache; }
     164                 :            : 
     165                 :            :     /**
     166                 :            :      * \brief
     167                 :            :      * Adds a QgsAbstractCacheIndex to this cache. Cache indices know about features present
     168                 :            :      * in this cache and decide, if enough information is present in the cache to respond to a QgsFeatureRequest.
     169                 :            :      * The layer cache will take ownership of the index.
     170                 :            :      *
     171                 :            :      * \param cacheIndex  The cache index to add.
     172                 :            :      */
     173                 :            :     void addCacheIndex( QgsAbstractCacheIndex *cacheIndex SIP_TRANSFER );
     174                 :            : 
     175                 :            :     /**
     176                 :            :      * Query this VectorLayerCache for features.
     177                 :            :      * If the VectorLayerCache (and moreover any of its indices) is able to satisfy
     178                 :            :      * the request, the returned QgsFeatureIterator will iterate over cached features.
     179                 :            :      * If it's not possible to fully satisfy the request from the cache, part or all of the features
     180                 :            :      * will be requested from the data provider.
     181                 :            :      * \param featureRequest  The request specifying filter and required data.
     182                 :            :      * \returns An iterator over the requested data.
     183                 :            :      */
     184                 :            :     QgsFeatureIterator getFeatures( const QgsFeatureRequest &featureRequest = QgsFeatureRequest() );
     185                 :            : 
     186                 :            :     /**
     187                 :            :      * Query the layer for features matching a given expression.
     188                 :            :      */
     189                 :            :     inline QgsFeatureIterator getFeatures( const QString &expression )
     190                 :            :     {
     191                 :            :       return getFeatures( QgsFeatureRequest( expression ) );
     192                 :            :     }
     193                 :            : 
     194                 :            :     /**
     195                 :            :      * Query the layer for the feature with the given id.
     196                 :            :      * If there is no such feature, the returned feature will be invalid.
     197                 :            :      */
     198                 :            :     inline QgsFeature getFeature( QgsFeatureId fid )
     199                 :            :     {
     200                 :            :       QgsFeature feature;
     201                 :            :       getFeatures( QgsFeatureRequest( fid ) ).nextFeature( feature );
     202                 :            :       return feature;
     203                 :            :     }
     204                 :            : 
     205                 :            :     /**
     206                 :            :      * Query the layer for the features with the given ids.
     207                 :            :      */
     208                 :            :     inline QgsFeatureIterator getFeatures( const QgsFeatureIds &fids )
     209                 :            :     {
     210                 :            :       return getFeatures( QgsFeatureRequest( fids ) );
     211                 :            :     }
     212                 :            : 
     213                 :            :     /**
     214                 :            :      * Query the layer for the features which intersect the specified rectangle.
     215                 :            :      */
     216                 :            :     inline QgsFeatureIterator getFeatures( const QgsRectangle &rectangle )
     217                 :            :     {
     218                 :            :       return getFeatures( QgsFeatureRequest( rectangle ) );
     219                 :            :     }
     220                 :            : 
     221                 :            :     /**
     222                 :            :      * Check if a certain feature id is cached.
     223                 :            :      * \param  fid The feature id to look for
     224                 :            :      * \returns TRUE if this id is in the cache
     225                 :            :      * \see cachedFeatureIds()
     226                 :            :      */
     227                 :            :     bool isFidCached( QgsFeatureId fid ) const;
     228                 :            : 
     229                 :            :     /**
     230                 :            :      * Returns the set of feature IDs for features which are cached.
     231                 :            :      * \see isFidCached()
     232                 :            :      * \since QGIS 3.0
     233                 :            :      */
     234                 :          0 :     QgsFeatureIds cachedFeatureIds() const { return qgis::listToSet( mCache.keys() ); }
     235                 :            : 
     236                 :            :     /**
     237                 :            :      * Gets the feature at the given feature id. Considers the changed, added, deleted and permanent features
     238                 :            :      * \param featureId The id of the feature to query
     239                 :            :      * \param feature   The result of the operation will be written to this feature
     240                 :            :      * \param skipCache Will query the layer regardless if the feature is in the cache already
     241                 :            :      * \returns TRUE in case of success
     242                 :            :      */
     243                 :            :     bool featureAtId( QgsFeatureId featureId, QgsFeature &feature, bool skipCache = false );
     244                 :            : 
     245                 :            :     /**
     246                 :            :      * Removes the feature identified by fid from the cache if present.
     247                 :            :      * \param fid The id of the feature to delete
     248                 :            :      * \returns TRUE if the feature was removed, FALSE if the feature id was not found in the cache
     249                 :            :      */
     250                 :            :     bool removeCachedFeature( QgsFeatureId fid );
     251                 :            : 
     252                 :            :     /**
     253                 :            :      * Returns the layer to which this cache belongs
     254                 :            :      */
     255                 :            :     QgsVectorLayer *layer();
     256                 :            : 
     257                 :            :     /**
     258                 :            :      * Returns the coordinate reference system for features in the cache.
     259                 :            :      */
     260                 :            :     QgsCoordinateReferenceSystem sourceCrs() const;
     261                 :            : 
     262                 :            :     /**
     263                 :            :      * Returns the fields associated with features in the cache.
     264                 :            :      */
     265                 :            :     QgsFields fields() const;
     266                 :            : 
     267                 :            :     /**
     268                 :            :      * Returns the geometry type for features in the cache.
     269                 :            :      */
     270                 :            :     QgsWkbTypes::Type wkbType() const;
     271                 :            : 
     272                 :            : #ifdef SIP_RUN
     273                 :            : 
     274                 :            :     /**
     275                 :            :      * Returns the number of features contained in the source, or -1
     276                 :            :      * if the feature count is unknown.
     277                 :            :      */
     278                 :            :     int __len__() const;
     279                 :            :     % MethodCode
     280                 :            :     sipRes = sipCpp->featureCount();
     281                 :            :     % End
     282                 :            : 
     283                 :            :     //! Ensures that bool(obj) returns TRUE (otherwise __len__() would be used)
     284                 :            :     int __bool__() const;
     285                 :            :     % MethodCode
     286                 :            :     sipRes = true;
     287                 :            :     % End
     288                 :            : #endif
     289                 :            : 
     290                 :            :     /**
     291                 :            :      * Returns the number of features contained in the source, or -1
     292                 :            :      * if the feature count is unknown.
     293                 :            :      */
     294                 :            :     long featureCount() const;
     295                 :            : 
     296                 :            :   protected:
     297                 :            : 
     298                 :            :     /**
     299                 :            :      * \brief
     300                 :            :      * Gets called, whenever the full list of feature ids for a certain request is known.
     301                 :            :      * Broadcasts this information to indices, so they can update their tables.
     302                 :            :      *
     303                 :            :      * \param featureRequest  The feature request that was answered
     304                 :            :      * \param fids            The feature ids that have been returned
     305                 :            :      */
     306                 :            :     void requestCompleted( const QgsFeatureRequest &featureRequest, const QgsFeatureIds &fids );
     307                 :            : 
     308                 :            :     /**
     309                 :            :      * \brief
     310                 :            :      * Gets called, whenever a feature has been removed.
     311                 :            :      * Broadcasts this information to indices, so they can invalidate their cache if required.
     312                 :            :      *
     313                 :            :      * \param fid             The feature id of the removed feature.
     314                 :            :      */
     315                 :            :     void featureRemoved( QgsFeatureId fid );
     316                 :            : 
     317                 :            :     /**
     318                 :            :      * \brief
     319                 :            :      * Checks if the information required to complete the request is cached.
     320                 :            :      * i.e. If all attributes required and the geometry is held in the cache.
     321                 :            :      * Please note, that this does not check, if the requested features are cached.
     322                 :            :      *
     323                 :            :      *
     324                 :            :      * \param featureRequest  The QgsFeatureRequest to be answered
     325                 :            :      * \returns                TRUE if the information is being cached, FALSE if not
     326                 :            :      */
     327                 :            :     bool checkInformationCovered( const QgsFeatureRequest &featureRequest );
     328                 :            : 
     329                 :            : 
     330                 :            :   signals:
     331                 :            : 
     332                 :            :     /**
     333                 :            :      * When filling the cache, this signal gets emitted periodically to notify about the progress
     334                 :            :      * and to be able to cancel an operation.
     335                 :            :      *
     336                 :            :      * \param i       The number of already fetched features
     337                 :            :      * \param cancel  A reference to a boolean variable. Set to TRUE and the operation will be canceled.
     338                 :            :      *
     339                 :            :      * \note not available in Python bindings
     340                 :            :      */
     341                 :            :     void progress( int i, bool &cancel ) SIP_SKIP;
     342                 :            : 
     343                 :            :     /**
     344                 :            :      * When filling the cache, this signal gets emitted once the cache is fully initialized.
     345                 :            :      */
     346                 :            :     void finished();
     347                 :            : 
     348                 :            :     /**
     349                 :            :      * \brief Is emitted when the cached layer is deleted. Is emitted when the cached layers layerDelete()
     350                 :            :      * signal is being emitted, but before the local reference to it has been set to NULLPTR. So call to
     351                 :            :      * layer() will still return a valid pointer for cleanup purpose.
     352                 :            :      */
     353                 :            :     void cachedLayerDeleted();
     354                 :            : 
     355                 :            :     /**
     356                 :            :      * Emitted when an attribute is changed. Is re-emitted after the layer itself emits this signal.
     357                 :            :      * You should connect to this signal, to be sure, to not get a cached value if querying the cache.
     358                 :            :      */
     359                 :            :     void attributeValueChanged( QgsFeatureId fid, int field, const QVariant &value );
     360                 :            : 
     361                 :            :     /**
     362                 :            :      * Emitted when a new feature has been added to the layer and this cache.
     363                 :            :      * You should connect to this signal instead of the layers', if you want to be sure
     364                 :            :      * that this cache has updated information for the new feature
     365                 :            :      *
     366                 :            :      * \param fid The featureid of the changed feature
     367                 :            :      */
     368                 :            :     void featureAdded( QgsFeatureId fid );
     369                 :            : 
     370                 :            :     /**
     371                 :            :      * The cache has been invalidated and cleared. Note that when a cache is invalidated
     372                 :            :      * the fullCache() setting will be cleared, and a full cache rebuild via setFullCache( TRUE )
     373                 :            :      * will need to be performed.
     374                 :            :      */
     375                 :            :     void invalidated();
     376                 :            : 
     377                 :            :   private slots:
     378                 :            :     void onAttributeValueChanged( QgsFeatureId fid, int field, const QVariant &value );
     379                 :            :     void onJoinAttributeValueChanged( QgsFeatureId fid, int field, const QVariant &value );
     380                 :            :     void featureDeleted( QgsFeatureId fid );
     381                 :            :     void onFeatureAdded( QgsFeatureId fid );
     382                 :            :     void attributeAdded( int field );
     383                 :            :     void attributeDeleted( int field );
     384                 :            :     void geometryChanged( QgsFeatureId fid, const QgsGeometry &geom );
     385                 :            :     void layerDeleted();
     386                 :            :     void invalidate();
     387                 :            : 
     388                 :            :   private:
     389                 :            : 
     390                 :            :     void connectJoinedLayers() const;
     391                 :            : 
     392                 :          0 :     inline void cacheFeature( QgsFeature &feat )
     393                 :            :     {
     394                 :          0 :       QgsCachedFeature *cachedFeature = new QgsCachedFeature( feat, this );
     395                 :          0 :       mCache.insert( feat.id(), cachedFeature );
     396                 :          0 :       if ( !mCacheOrderedKeys.contains( feat.id() ) )
     397                 :          0 :         mCacheOrderedKeys << feat.id();
     398                 :          0 :     }
     399                 :            : 
     400                 :            :     QgsVectorLayer *mLayer = nullptr;
     401                 :            :     QCache< QgsFeatureId, QgsCachedFeature > mCache;
     402                 :            :     QList< QgsFeatureId > mCacheOrderedKeys;
     403                 :            : 
     404                 :            :     bool mCacheGeometry = true;
     405                 :            :     bool mFullCache = false;
     406                 :            :     QList<QgsAbstractCacheIndex *> mCacheIndices;
     407                 :            : 
     408                 :            :     QgsAttributeList mCachedAttributes;
     409                 :            : 
     410                 :            :     friend class QgsCachedFeatureIterator;
     411                 :            :     friend class QgsCachedFeatureWriterIterator;
     412                 :            :     friend class QgsCachedFeature;
     413                 :            : 
     414                 :            :     /**
     415                 :            :      * Returns TRUE if the cache contains all the features required for a specified request.
     416                 :            :      * \param featureRequest feature request
     417                 :            :      * \param it will be set to iterator for matching features
     418                 :            :      * \returns TRUE if cache can satisfy request
     419                 :            :      * \note this method only checks for available features, not whether the cache
     420                 :            :      * contains required attributes or geometry. For that, use checkInformationCovered()
     421                 :            :      */
     422                 :            :     bool canUseCacheForRequest( const QgsFeatureRequest &featureRequest, QgsFeatureIterator &it );
     423                 :            : 
     424                 :            :     friend class TestVectorLayerCache;
     425                 :            : };
     426                 :            : #endif // QgsVectorLayerCache_H

Generated by: LCOV version 1.14