Exemplo n.º 1
0
QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayerFeatureSource* source, bool ownSource, const QgsFeatureRequest& request )
    : QgsAbstractFeatureIteratorFromSource( source, ownSource, request )
    , mEditGeometrySimplifier( 0 )
{

  // prepare joins: may add more attributes to fetch (in order to allow join)
  if ( mSource->mJoinBuffer->containsJoins() )
    prepareJoins();

  prepareExpressions();

  // by default provider's request is the same
  mProviderRequest = mRequest;

  if ( mProviderRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
  {
    // prepare list of attributes to match provider fields
    QgsAttributeList providerSubset;
    QgsAttributeList subset = mProviderRequest.subsetOfAttributes();
    int nPendingFields = mSource->mFields.count();
    for ( int i = 0; i < subset.count(); ++i )
    {
      int attrIndex = subset[i];
      if ( attrIndex < 0 || attrIndex >= nPendingFields ) continue;
      if ( mSource->mFields.fieldOrigin( attrIndex ) == QgsFields::OriginProvider )
        providerSubset << mSource->mFields.fieldOriginIndex( attrIndex );
    }
    mProviderRequest.setSubsetOfAttributes( providerSubset );
  }

  if ( mSource->mHasEditBuffer )
  {
    mChangedFeaturesRequest = mProviderRequest;
    mChangedFeaturesRequest.setFilterFids( mSource->mChangedAttributeValues.keys().toSet() );
  }

  if ( request.filterType() == QgsFeatureRequest::FilterFid )
  {
    mFetchedFid = false;
  }
  else // no filter or filter by rect
  {
    if ( mSource->mHasEditBuffer )
    {
      mChangedFeaturesIterator = mSource->mProviderFeatureSource->getFeatures( mChangedFeaturesRequest );
    }
    else
    {
      mProviderIterator = mSource->mProviderFeatureSource->getFeatures( mProviderRequest );
    }

    rewindEditBuffer();
  }

  if ( mRequest.filterType() == QgsFeatureRequest::FilterExpression )
  {
    mRequest.filterExpression()->prepare( mSource->mFields );
  }
}
QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* layer, const QgsFeatureRequest& request )
    : QgsAbstractFeatureIterator( request ), L( layer )
{
  QgsVectorLayerJoinBuffer* joinBuffer = L->mJoinBuffer;

  if ( L->editBuffer() )
  {
    mAddedFeatures = QgsFeatureMap( L->editBuffer()->addedFeatures() );
    mChangedGeometries = QgsGeometryMap( L->editBuffer()->changedGeometries() );
    mDeletedFeatureIds = QgsFeatureIds( L->editBuffer()->deletedFeatureIds() );
    mChangedAttributeValues = QgsChangedAttributesMap( L->editBuffer()->changedAttributeValues() );
    mAddedAttributes = QList<QgsField>( L->editBuffer()->addedAttributes() );
    mDeletedAttributeIds = QgsAttributeList( L->editBuffer()->deletedAttributeIds() );
  }

  // prepare joins: may add more attributes to fetch (in order to allow join)
  if ( joinBuffer->containsJoins() )
    prepareJoins();

  // by default provider's request is the same
  mProviderRequest = mRequest;

  if ( mProviderRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
  {
    // prepare list of attributes to match provider fields
    QgsAttributeList providerSubset;
    QgsAttributeList subset = mProviderRequest.subsetOfAttributes();
    const QgsFields &pendingFields = L->pendingFields();
    int nPendingFields = pendingFields.count();
    for ( int i = 0; i < subset.count(); ++i )
    {
      int attrIndex = subset[i];
      if ( attrIndex < 0 || attrIndex >= nPendingFields ) continue;
      if ( L->pendingFields().fieldOrigin( attrIndex ) == QgsFields::OriginProvider )
        providerSubset << L->pendingFields().fieldOriginIndex( attrIndex );
    }
    mProviderRequest.setSubsetOfAttributes( providerSubset );
  }

  if ( request.filterType() == QgsFeatureRequest::FilterFid )
  {
    mFetchedFid = false;
  }
  else // no filter or filter by rect
  {
    mProviderIterator = L->dataProvider()->getFeatures( mProviderRequest );

    rewindEditBuffer();
  }
}
QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayerFeatureSource* source, bool ownSource, const QgsFeatureRequest& request )
    : QgsAbstractFeatureIteratorFromSource<QgsVectorLayerFeatureSource>( source, ownSource, request )
    , mFetchedFid( false )
    , mEditGeometrySimplifier( 0 )
{
  prepareExpressions();

  // prepare joins: may add more attributes to fetch (in order to allow join)
  if ( mSource->mJoinBuffer->containsJoins() )
    prepareJoins();

  mHasVirtualAttributes = !mFetchJoinInfo.isEmpty() || !mExpressionFieldInfo.isEmpty();

  // by default provider's request is the same
  mProviderRequest = mRequest;

  if ( mProviderRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
  {
    // prepare list of attributes to match provider fields
    QgsAttributeList providerSubset;
    QgsAttributeList subset = mProviderRequest.subsetOfAttributes();
    int nPendingFields = mSource->mFields.count();
    for ( int i = 0; i < subset.count(); ++i )
    {
      int attrIndex = subset[i];
      if ( attrIndex < 0 || attrIndex >= nPendingFields ) continue;
      if ( mSource->mFields.fieldOrigin( attrIndex ) == QgsFields::OriginProvider )
        providerSubset << mSource->mFields.fieldOriginIndex( attrIndex );
    }
    mProviderRequest.setSubsetOfAttributes( providerSubset );
  }

  if ( mProviderRequest.filterType() == QgsFeatureRequest::FilterExpression )
  {
    Q_FOREACH ( const QString& field, mProviderRequest.filterExpression()->referencedColumns() )
    {
      int idx = source->mFields.fieldNameIndex( field );

      // If there are fields in the expression which are not of origin provider, the provider will not be able to filter based on them.
      // In this case we disable the expression filter.
      if ( source->mFields.fieldOrigin( idx ) != QgsFields::OriginProvider )
      {
        mProviderRequest.disableFilter();
      }
    }
  }
QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayerFeatureSource* source, bool ownSource, const QgsFeatureRequest& request )
    : QgsAbstractFeatureIteratorFromSource<QgsVectorLayerFeatureSource>( source, ownSource, request )
    , mFetchedFid( false )
    , mEditGeometrySimplifier( nullptr )
    , mInterruptionChecker( nullptr )
{
  prepareExpressions();

  // prepare joins: may add more attributes to fetch (in order to allow join)
  if ( mSource->mJoinBuffer->containsJoins() )
    prepareJoins();

  mHasVirtualAttributes = !mFetchJoinInfo.isEmpty() || !mExpressionFieldInfo.isEmpty();

  // by default provider's request is the same
  mProviderRequest = mRequest;

  if ( mProviderRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
  {
    // prepare list of attributes to match provider fields
    QSet<int> providerSubset;
    QgsAttributeList subset = mProviderRequest.subsetOfAttributes();
    int nPendingFields = mSource->mFields.count();
    Q_FOREACH ( int attrIndex, subset )
    {
      if ( attrIndex < 0 || attrIndex >= nPendingFields ) continue;
      if ( mSource->mFields.fieldOrigin( attrIndex ) == QgsFields::OriginProvider )
        providerSubset << mSource->mFields.fieldOriginIndex( attrIndex );
    }

    // This is done in order to be prepared to do fallback order bys
    // and be sure we have the required columns.
    // TODO:
    // It would be nicer to first check if we can compile the order by
    // and only modify the subset if we cannot.
    if ( !mProviderRequest.orderBy().isEmpty() )
    {
      Q_FOREACH ( const QString& attr, mProviderRequest.orderBy().usedAttributes() )
      {
        providerSubset << mSource->mFields.fieldNameIndex( attr );
      }
    }