mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
Remove QgsFeatureRequest::FilterRect from providers/iterators
This commit is contained in:
parent
75712643cd
commit
5be0ee734f
@ -801,7 +801,12 @@ class QgsVectorLayer : QgsMapLayer
|
||||
/** Return the extent of the layer as a QRect */
|
||||
QgsRectangle extent();
|
||||
|
||||
/** Returns field list in the to-be-committed state */
|
||||
/**
|
||||
* Returns the list of fields of this layer.
|
||||
* This also includes fields which have not yet been saved to the provider.
|
||||
*
|
||||
* @return A list of fields
|
||||
*/
|
||||
const QgsFields &pendingFields() const;
|
||||
|
||||
/** Returns list of attributes */
|
||||
|
@ -2220,11 +2220,6 @@ bool QgsVectorLayer::deleteFeature( QgsFeatureId fid )
|
||||
return res;
|
||||
}
|
||||
|
||||
const QgsFields &QgsVectorLayer::pendingFields() const
|
||||
{
|
||||
return mUpdatedFields;
|
||||
}
|
||||
|
||||
QgsAttributeList QgsVectorLayer::pendingAllAttributesList()
|
||||
{
|
||||
return mUpdatedFields.allAttributesList();
|
||||
|
@ -1300,8 +1300,13 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
|
||||
/** Return the extent of the layer as a QRect */
|
||||
QgsRectangle extent() override;
|
||||
|
||||
/** Returns field list in the to-be-committed state */
|
||||
const QgsFields &pendingFields() const;
|
||||
/**
|
||||
* Returns the list of fields of this layer.
|
||||
* This also includes fields which have not yet been saved to the provider.
|
||||
*
|
||||
* @return A list of fields
|
||||
*/
|
||||
const QgsFields &pendingFields() const { return mUpdatedFields; }
|
||||
|
||||
/** Returns list of attributes */
|
||||
QgsAttributeList pendingAllAttributesList();
|
||||
|
@ -176,7 +176,7 @@ bool QgsVectorLayerFeatureIterator::fetchFeature( QgsFeature& f )
|
||||
return res;
|
||||
}
|
||||
|
||||
if ( mRequest.filterType() == QgsFeatureRequest::FilterRect )
|
||||
if ( !mRequest.filterRect().isNull() )
|
||||
{
|
||||
if ( fetchNextChangedGeomFeature( f ) )
|
||||
return true;
|
||||
@ -352,6 +352,10 @@ bool QgsVectorLayerFeatureIterator::fetchNextChangedAttributeFeature( QgsFeature
|
||||
{
|
||||
while ( mChangedFeaturesIterator.nextFeature( f ) )
|
||||
{
|
||||
if ( mFetchConsidered.contains( f.id() ) )
|
||||
// skip deleted features and those already handled by the geometry
|
||||
continue;
|
||||
|
||||
mFetchConsidered << f.id();
|
||||
|
||||
updateChangedAttributes( f );
|
||||
@ -359,14 +363,7 @@ bool QgsVectorLayerFeatureIterator::fetchNextChangedAttributeFeature( QgsFeature
|
||||
if ( mHasVirtualAttributes )
|
||||
addVirtualAttributes( f );
|
||||
|
||||
if ( mRequest.filterType() == QgsFeatureRequest::FilterExpression )
|
||||
{
|
||||
if ( mRequest.filterExpression()->evaluate( &f ).toBool() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
if ( mRequest.filterExpression()->evaluate( &f ).toBool() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -136,6 +136,7 @@ bool QgsVectorLayerRenderer::render()
|
||||
|
||||
QgsRenderOptions opts = mRendererV2->startRender( mContext, mFields );
|
||||
|
||||
QgsDebugMsg( opts.whereClause() );
|
||||
QgsRectangle requestExtent = mContext.extent();
|
||||
mRendererV2->modifyRequestExtent( requestExtent, mContext );
|
||||
|
||||
|
@ -44,21 +44,8 @@ QgsDelimitedTextFeatureIterator::QgsDelimitedTextFeatureIterator( QgsDelimitedTe
|
||||
mTestGeometry = false;
|
||||
|
||||
mMode = FileScan;
|
||||
if ( request.filterType() == QgsFeatureRequest::FilterFid )
|
||||
{
|
||||
QgsDebugMsg( "Configuring for returning single id" );
|
||||
mFeatureIds.append( request.filterFid() );
|
||||
mMode = FeatureIds;
|
||||
mTestSubset = false;
|
||||
}
|
||||
// If have geometry and testing geometry then evaluate options...
|
||||
// If we don't have geometry then all records pass geometry filter.
|
||||
// CC: 2013-05-09
|
||||
// Not sure about intended relationship between filtering on geometry and
|
||||
// requesting no geometry? Have preserved current logic of ignoring spatial filter
|
||||
// if not requesting geometry.
|
||||
|
||||
else if ( request.filterType() == QgsFeatureRequest::FilterRect && hasGeometry )
|
||||
if ( !request.filterRect().isNull() && hasGeometry )
|
||||
{
|
||||
QgsDebugMsg( "Configuring for rectangle select" );
|
||||
mTestGeometry = true;
|
||||
@ -98,13 +85,32 @@ QgsDelimitedTextFeatureIterator::QgsDelimitedTextFeatureIterator( QgsDelimitedTe
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a subset index then use it..
|
||||
if ( mMode == FileScan && mSource->mUseSubsetIndex )
|
||||
if ( request.filterType() == QgsFeatureRequest::FilterFid )
|
||||
{
|
||||
QgsDebugMsg( QString( "Layer has subset index - use %1 items from subset index" ).arg( mSource->mSubsetIndex.size() ) );
|
||||
QgsDebugMsg( "Configuring for returning single id" );
|
||||
if ( request.filterRect().isNull() || ( !request.filterRect().isNull() && mFeatureIds.contains( request.filterFid() ) ) )
|
||||
{
|
||||
mFeatureIds = QList<QgsFeatureId>() << request.filterFid();
|
||||
}
|
||||
mMode = FeatureIds;
|
||||
mTestSubset = false;
|
||||
mMode = SubsetIndex;
|
||||
}
|
||||
// If have geometry and testing geometry then evaluate options...
|
||||
// If we don't have geometry then all records pass geometry filter.
|
||||
// CC: 2013-05-09
|
||||
// Not sure about intended relationship between filtering on geometry and
|
||||
// requesting no geometry? Have preserved current logic of ignoring spatial filter
|
||||
// if not requesting geometry.
|
||||
|
||||
else
|
||||
|
||||
// If we have a subset index then use it..
|
||||
if ( mMode == FileScan && mSource->mUseSubsetIndex )
|
||||
{
|
||||
QgsDebugMsg( QString( "Layer has subset index - use %1 items from subset index" ).arg( mSource->mSubsetIndex.size() ) );
|
||||
mTestSubset = false;
|
||||
mMode = SubsetIndex;
|
||||
}
|
||||
|
||||
// Otherwise just have to scan the file
|
||||
if ( mMode == FileScan )
|
||||
|
@ -176,7 +176,7 @@ bool QgsGPXFeatureIterator::readFid( QgsFeature& feature )
|
||||
|
||||
bool QgsGPXFeatureIterator::readWaypoint( const QgsWaypoint& wpt, QgsFeature& feature )
|
||||
{
|
||||
if ( mRequest.filterType() == QgsFeatureRequest::FilterRect )
|
||||
if ( !mRequest.filterRect().isNull() )
|
||||
{
|
||||
const QgsRectangle& rect = mRequest.filterRect();
|
||||
if ( ! rect.contains( QgsPoint( wpt.lon, wpt.lat ) ) )
|
||||
@ -206,7 +206,7 @@ bool QgsGPXFeatureIterator::readRoute( const QgsRoute& rte, QgsFeature& feature
|
||||
|
||||
QgsGeometry* theGeometry = readRouteGeometry( rte );
|
||||
|
||||
if ( mRequest.filterType() == QgsFeatureRequest::FilterRect )
|
||||
if ( !mRequest.filterRect().isNull() )
|
||||
{
|
||||
const QgsRectangle& rect = mRequest.filterRect();
|
||||
if (( rte.xMax < rect.xMinimum() ) || ( rte.xMin > rect.xMaximum() ) ||
|
||||
@ -248,7 +248,7 @@ bool QgsGPXFeatureIterator::readTrack( const QgsTrack& trk, QgsFeature& feature
|
||||
|
||||
QgsGeometry* theGeometry = readTrackGeometry( trk );
|
||||
|
||||
if ( mRequest.filterType() == QgsFeatureRequest::FilterRect )
|
||||
if ( !mRequest.filterRect().isNull() )
|
||||
{
|
||||
const QgsRectangle& rect = mRequest.filterRect();
|
||||
if (( trk.xMax < rect.xMinimum() ) || ( trk.xMin > rect.xMaximum() ) ||
|
||||
|
@ -80,7 +80,7 @@ QgsGrassFeatureIterator::QgsGrassFeatureIterator( QgsGrassFeatureSource* source,
|
||||
allocateSelection( mSource->mMap );
|
||||
resetSelection( 1 );
|
||||
|
||||
if ( request.filterType() == QgsFeatureRequest::FilterRect )
|
||||
if ( !request.filterRect().isNull() )
|
||||
{
|
||||
setSelectionRect( request.filterRect(), request.flags() & QgsFeatureRequest::ExactIntersect );
|
||||
}
|
||||
|
@ -33,14 +33,14 @@ QgsMemoryFeatureIterator::QgsMemoryFeatureIterator( QgsMemoryFeatureSource* sour
|
||||
mSubsetExpression->prepare( mSource->mFields );
|
||||
}
|
||||
|
||||
if ( mRequest.filterType() == QgsFeatureRequest::FilterRect && mRequest.flags() & QgsFeatureRequest::ExactIntersect )
|
||||
if ( !mRequest.filterRect().isNull() && mRequest.flags() & QgsFeatureRequest::ExactIntersect )
|
||||
{
|
||||
mSelectRectGeom = QgsGeometry::fromRect( request.filterRect() );
|
||||
}
|
||||
|
||||
// if there's spatial index, use it!
|
||||
// (but don't use it when selection rect is not specified)
|
||||
if ( mRequest.filterType() == QgsFeatureRequest::FilterRect && mSource->mSpatialIndex )
|
||||
if ( !mRequest.filterRect().isNull() && mSource->mSpatialIndex )
|
||||
{
|
||||
mUsingFeatureIdList = true;
|
||||
mFeatureIdList = mSource->mSpatialIndex->intersects( mRequest.filterRect() );
|
||||
@ -90,7 +90,7 @@ bool QgsMemoryFeatureIterator::nextFeatureUsingList( QgsFeature& feature )
|
||||
// option 1: we have a list of features to traverse
|
||||
while ( mFeatureIdListIterator != mFeatureIdList.constEnd() )
|
||||
{
|
||||
if ( mRequest.filterType() == QgsFeatureRequest::FilterRect && mRequest.flags() & QgsFeatureRequest::ExactIntersect )
|
||||
if ( !mRequest.filterRect().isNull() && mRequest.flags() & QgsFeatureRequest::ExactIntersect )
|
||||
{
|
||||
// do exact check in case we're doing intersection
|
||||
if ( mSource->mFeatures[*mFeatureIdListIterator].geometry() && mSource->mFeatures[*mFeatureIdListIterator].geometry()->intersects( mSelectRectGeom ) )
|
||||
@ -131,7 +131,7 @@ bool QgsMemoryFeatureIterator::nextFeatureTraverseAll( QgsFeature& feature )
|
||||
// option 2: traversing the whole layer
|
||||
while ( mSelectIterator != mSource->mFeatures.constEnd() )
|
||||
{
|
||||
if ( mRequest.filterType() != QgsFeatureRequest::FilterRect )
|
||||
if ( mRequest.filterRect().isNull() )
|
||||
{
|
||||
// selection rect empty => using all features
|
||||
hasFeature = true;
|
||||
|
@ -89,7 +89,7 @@ void QgsMssqlFeatureIterator::BuildStatement( const QgsFeatureRequest& request )
|
||||
|
||||
bool filterAdded = false;
|
||||
// set spatial filter
|
||||
if ( request.filterType() == QgsFeatureRequest::FilterRect && mSource->isSpatial() && !request.filterRect().isEmpty() )
|
||||
if ( !request.filterRect().isNull() && mSource->isSpatial() && !request.filterRect().isEmpty() )
|
||||
{
|
||||
// polygons should be CCW for SqlGeography
|
||||
QString r;
|
||||
|
@ -58,20 +58,20 @@ QgsOgrFeatureIterator::QgsOgrFeatureIterator( QgsOgrFeatureSource* source, bool
|
||||
mSubsetStringSet = true;
|
||||
}
|
||||
|
||||
mFetchGeometry = ( mRequest.filterType() == QgsFeatureRequest::FilterRect ) || !( mRequest.flags() & QgsFeatureRequest::NoGeometry );
|
||||
mFetchGeometry = ( !mRequest.filterRect().isNull() ) || !( mRequest.flags() & QgsFeatureRequest::NoGeometry );
|
||||
QgsAttributeList attrs = ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) ? mRequest.subsetOfAttributes() : mSource->mFields.allAttributesList();
|
||||
|
||||
// make sure we fetch just relevant fields
|
||||
// unless it's a VRT data source filtered by geometry as we don't know which
|
||||
// attributes make up the geometry and OGR won't fetch them to evaluate the
|
||||
// filter if we choose to ignore them (fixes #11223)
|
||||
if (( mSource->mDriverName != "VRT" && mSource->mDriverName != "OGR_VRT" ) || mRequest.filterType() != QgsFeatureRequest::FilterRect )
|
||||
if (( mSource->mDriverName != "VRT" && mSource->mDriverName != "OGR_VRT" ) || mRequest.filterRect().isNull() )
|
||||
{
|
||||
QgsOgrUtils::setRelevantFields( ogrLayer, mSource->mFields.count(), mFetchGeometry, attrs );
|
||||
}
|
||||
|
||||
// spatial query to select features
|
||||
if ( mRequest.filterType() == QgsFeatureRequest::FilterRect )
|
||||
if ( !mRequest.filterRect().isNull() )
|
||||
{
|
||||
const QgsRectangle& rect = mRequest.filterRect();
|
||||
|
||||
@ -179,7 +179,7 @@ bool QgsOgrFeatureIterator::fetchFeature( QgsFeature& feature )
|
||||
if ( !readFeature( fet, feature ) )
|
||||
continue;
|
||||
|
||||
if ( mRequest.filterType() == QgsFeatureRequest::FilterRect && !feature.constGeometry() )
|
||||
if ( !mRequest.filterRect().isNull() && !feature.constGeometry() )
|
||||
continue;
|
||||
|
||||
// we have a feature, end this cycle
|
||||
|
@ -46,45 +46,49 @@ QgsOracleFeatureIterator::QgsOracleFeatureIterator( QgsOracleFeatureSource* sour
|
||||
|
||||
QString whereClause;
|
||||
|
||||
if ( !mRequest.filterRect().isNull && !mSource->mGeometryColumn.isNull() && mSource->mHasSpatialIndex )
|
||||
{
|
||||
QgsRectangle rect( mRequest.filterRect() );
|
||||
QString bbox = QString( "mdsys.sdo_geometry(2003,%1,NULL,"
|
||||
"mdsys.sdo_elem_info_array(1,1003,3),"
|
||||
"mdsys.sdo_ordinate_array(%2,%3,%4,%5)"
|
||||
")" )
|
||||
.arg( mSource->mSrid < 1 ? "NULL" : QString::number( mSource->mSrid ) )
|
||||
.arg( qgsDoubleToString( rect.xMinimum() ) )
|
||||
.arg( qgsDoubleToString( rect.yMinimum() ) )
|
||||
.arg( qgsDoubleToString( rect.xMaximum() ) )
|
||||
.arg( qgsDoubleToString( rect.yMaximum() ) );
|
||||
|
||||
whereClause = QString( "sdo_filter(%1,%2)='TRUE'" ).arg( QgsOracleProvider::quotedIdentifier( mSource->mGeometryColumn ) ).arg( bbox );
|
||||
|
||||
if ( mRequest.flags() & QgsFeatureRequest::ExactIntersect && mConnection->hasSpatial() )
|
||||
{
|
||||
whereClause += QString( " AND sdo_relate(%1,%2,'mask=ANYINTERACT')='TRUE'" )
|
||||
.arg( QgsOracleProvider::quotedIdentifier( mSource->mGeometryColumn ) )
|
||||
.arg( bbox );
|
||||
}
|
||||
}
|
||||
|
||||
switch ( request.filterType() )
|
||||
{
|
||||
case QgsFeatureRequest::FilterFid:
|
||||
QString fidWhereClause = QgsOracleUtils::whereClause( request.filterFid(), mSource->mFields, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );
|
||||
whereClause = QgsPostgresUtils::andWhereClauses( whereClause, fidWhereClause );
|
||||
break;
|
||||
|
||||
case QgsFeatureRequest::FilterFids:
|
||||
QString fidsWhereClause = QgsOracleUtils::whereClause( request.filterFids(), mSource->mFields, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );
|
||||
whereClause = QgsPostgresUtils::andWhereClauses( whereClause, fidsWhereClause );
|
||||
break;
|
||||
|
||||
case QgsFeatureRequest::FilterNone:
|
||||
break;
|
||||
|
||||
case QgsFeatureRequest::FilterExpression:
|
||||
break;
|
||||
|
||||
case QgsFeatureRequest::FilterRect:
|
||||
if ( !mSource->mGeometryColumn.isNull() && mSource->mHasSpatialIndex )
|
||||
{
|
||||
QgsRectangle rect( mRequest.filterRect() );
|
||||
QString bbox = QString( "mdsys.sdo_geometry(2003,%1,NULL,"
|
||||
"mdsys.sdo_elem_info_array(1,1003,3),"
|
||||
"mdsys.sdo_ordinate_array(%2,%3,%4,%5)"
|
||||
")" )
|
||||
.arg( mSource->mSrid < 1 ? "NULL" : QString::number( mSource->mSrid ) )
|
||||
.arg( qgsDoubleToString( rect.xMinimum() ) )
|
||||
.arg( qgsDoubleToString( rect.yMinimum() ) )
|
||||
.arg( qgsDoubleToString( rect.xMaximum() ) )
|
||||
.arg( qgsDoubleToString( rect.yMaximum() ) );
|
||||
|
||||
whereClause = QString( "sdo_filter(%1,%2)='TRUE'" ).arg( QgsOracleProvider::quotedIdentifier( mSource->mGeometryColumn ) ).arg( bbox );
|
||||
|
||||
if ( mRequest.flags() & QgsFeatureRequest::ExactIntersect && mConnection->hasSpatial() )
|
||||
{
|
||||
whereClause += QString( " AND sdo_relate(%1,%2,'mask=ANYINTERACT')='TRUE'" )
|
||||
.arg( QgsOracleProvider::quotedIdentifier( mSource->mGeometryColumn ) )
|
||||
.arg( bbox );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case QgsFeatureRequest::FilterFid:
|
||||
whereClause = QgsOracleUtils::whereClause( request.filterFid(), mSource->mFields, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );
|
||||
break;
|
||||
|
||||
case QgsFeatureRequest::FilterFids:
|
||||
whereClause = QgsOracleUtils::whereClause( request.filterFids(), mSource->mFields, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );
|
||||
break;
|
||||
|
||||
case QgsFeatureRequest::FilterNone:
|
||||
// Handled in the if-statement above
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -464,6 +464,15 @@ QString QgsOracleUtils::whereClause( QgsFeatureIds featureIds, const QgsFields &
|
||||
return whereClauses.isEmpty() ? "" : whereClauses.join( " OR " ).prepend( "(" ).append( ")" );
|
||||
}
|
||||
|
||||
QString QgsOracleUtils::andWhereClauses( const QString& c1, const QString& c2 )
|
||||
{
|
||||
if ( c1.isNull() )
|
||||
return c2;
|
||||
if ( c2.isNull() )
|
||||
return c1;
|
||||
|
||||
return QString( "(%1) AND (%2)" ).arg( c1 ).arg( c2 );
|
||||
}
|
||||
|
||||
QString QgsOracleProvider::whereClause( QgsFeatureId featureId ) const
|
||||
{
|
||||
|
@ -423,6 +423,8 @@ class QgsOracleUtils
|
||||
QgsOraclePrimaryKeyType primaryKeyType,
|
||||
const QList<int>& primaryKeyAttrs,
|
||||
QSharedPointer<QgsOracleSharedData> sharedData );
|
||||
|
||||
static QString andWhereClauses( const QString& c1, const QString& c2 );
|
||||
};
|
||||
|
||||
|
||||
|
@ -184,9 +184,32 @@ QgsPostgresExpressionCompiler::Result QgsPostgresExpressionCompiler::compile( co
|
||||
return Complete;
|
||||
}
|
||||
|
||||
case QgsExpression::ntInOperator:
|
||||
{
|
||||
const QgsExpression::NodeInOperator* n = static_cast<const QgsExpression::NodeInOperator*>( node );
|
||||
QStringList list;
|
||||
|
||||
Q_FOREACH ( const QgsExpression::Node* ln, n->list()->list() )
|
||||
{
|
||||
QString s;
|
||||
Result r = compile( ln, s );
|
||||
if ( r == Complete )
|
||||
list << s;
|
||||
else
|
||||
return r;
|
||||
}
|
||||
|
||||
QString nd;
|
||||
Result rn = compile( n->node(), nd );
|
||||
if ( rn != Complete )
|
||||
return rn;
|
||||
|
||||
result = QString( "%1 %2IN(%3)" ).arg( nd ).arg( n->isNotIn() ? "NOT " : "" ).arg( list.join( "," ) );
|
||||
return Complete;
|
||||
}
|
||||
|
||||
case QgsExpression::ntFunction:
|
||||
case QgsExpression::ntCondition:
|
||||
case QgsExpression::ntInOperator:
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -58,17 +58,22 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresFeatureSource
|
||||
mCursorName = mConn->uniqueCursorName();
|
||||
QString whereClause;
|
||||
|
||||
if ( request.filterType() == QgsFeatureRequest::FilterRect && !mSource->mGeometryColumn.isNull() )
|
||||
if ( !request.filterRect().isNull() && !mSource->mGeometryColumn.isNull() )
|
||||
{
|
||||
whereClause = whereClauseRect();
|
||||
}
|
||||
else if ( request.filterType() == QgsFeatureRequest::FilterFid )
|
||||
|
||||
if ( request.filterType() == QgsFeatureRequest::FilterFid )
|
||||
{
|
||||
whereClause = QgsPostgresUtils::whereClause( mRequest.filterFid(), mSource->mFields, mConn, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );
|
||||
QString fidWhereClause = QgsPostgresUtils::whereClause( mRequest.filterFid(), mSource->mFields, mConn, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );
|
||||
|
||||
whereClause = QgsPostgresUtils::andWhereClauses( whereClause, fidWhereClause );
|
||||
}
|
||||
else if ( request.filterType() == QgsFeatureRequest::FilterFids )
|
||||
{
|
||||
whereClause = QgsPostgresUtils::whereClause( mRequest.filterFids(), mSource->mFields, mConn, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );
|
||||
QString fidsWhereClause = QgsPostgresUtils::whereClause( mRequest.filterFids(), mSource->mFields, mConn, mSource->mPrimaryKeyType, mSource->mPrimaryKeyAttrs, mSource->mShared );
|
||||
|
||||
whereClause = QgsPostgresUtils::andWhereClauses( whereClause, fidsWhereClause );
|
||||
}
|
||||
else if ( request.filterType() == QgsFeatureRequest::FilterExpression
|
||||
&& QSettings().value( "/qgis/postgres/compileExpressions", false ).toBool() )
|
||||
@ -77,7 +82,7 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresFeatureSource
|
||||
|
||||
if ( compiler.compile( request.filterExpression() ) == QgsPostgresExpressionCompiler::Complete )
|
||||
{
|
||||
whereClause = compiler.result();
|
||||
whereClause = QgsPostgresUtils::andWhereClauses( whereClause, compiler.result() );
|
||||
mExpressionCompiled = true;
|
||||
}
|
||||
}
|
||||
|
@ -548,6 +548,16 @@ QString QgsPostgresUtils::whereClause( QgsFeatureIds featureIds, const QgsFields
|
||||
return whereClauses.isEmpty() ? "" : whereClauses.join( " OR " ).prepend( "(" ).append( ")" );
|
||||
}
|
||||
|
||||
QString QgsPostgresUtils::andWhereClauses( const QString& c1, const QString& c2 )
|
||||
{
|
||||
if ( c1.isNull() )
|
||||
return c2;
|
||||
if ( c2.isNull() )
|
||||
return c1;
|
||||
|
||||
return QString( "(%1) AND (%2)" ).arg( c1 ).arg( c2 );
|
||||
}
|
||||
|
||||
QString QgsPostgresProvider::filterWhereClause() const
|
||||
{
|
||||
QString where;
|
||||
|
@ -501,6 +501,8 @@ class QgsPostgresUtils
|
||||
QgsPostgresPrimaryKeyType pkType,
|
||||
const QList<int>& pkAttrs,
|
||||
QSharedPointer<QgsPostgresSharedData> sharedData );
|
||||
|
||||
static QString andWhereClauses( const QString& c1, const QString& c2 );
|
||||
};
|
||||
|
||||
/** Data shared between provider class and its feature sources. Ideally there should
|
||||
|
@ -35,7 +35,7 @@ QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeature
|
||||
mRowNumber = 0;
|
||||
|
||||
QString whereClause;
|
||||
if ( request.filterType() == QgsFeatureRequest::FilterRect && !mSource->mGeometryColumn.isNull() )
|
||||
if ( !request.filterRect().isNull() && !mSource->mGeometryColumn.isNull() )
|
||||
{
|
||||
// some kind of MBR spatial filtering is required
|
||||
whereClause += whereClauseRect();
|
||||
@ -45,8 +45,7 @@ QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeature
|
||||
{
|
||||
whereClause += whereClauseFid();
|
||||
}
|
||||
|
||||
if ( request.filterType() == QgsFeatureRequest::FilterFids )
|
||||
else if ( request.filterType() == QgsFeatureRequest::FilterFids )
|
||||
{
|
||||
whereClause += whereClauseFids();
|
||||
}
|
||||
|
@ -21,20 +21,18 @@
|
||||
QgsWFSFeatureIterator::QgsWFSFeatureIterator( QgsWFSFeatureSource* source, bool ownSource, const QgsFeatureRequest& request )
|
||||
: QgsAbstractFeatureIteratorFromSource<QgsWFSFeatureSource>( source, ownSource, request )
|
||||
{
|
||||
switch ( request.filterType() )
|
||||
if ( !request.filterRect().isNull() && mSource->mSpatialIndex )
|
||||
{
|
||||
case QgsFeatureRequest::FilterRect:
|
||||
if ( mSource->mSpatialIndex )
|
||||
{
|
||||
mSelectedFeatures = mSource->mSpatialIndex->intersects( request.filterRect() );
|
||||
}
|
||||
break;
|
||||
case QgsFeatureRequest::FilterFid:
|
||||
mSelectedFeatures.push_back( request.filterFid() );
|
||||
break;
|
||||
case QgsFeatureRequest::FilterNone:
|
||||
default:
|
||||
mSelectedFeatures = mSource->mFeatures.keys();
|
||||
mSelectedFeatures = mSource->mSpatialIndex->intersects( request.filterRect() );
|
||||
}
|
||||
|
||||
if ( request.filterType() == QgsFeatureRequest::FilterFid )
|
||||
{
|
||||
mSelectedFeatures.push_back( request.filterFid() );
|
||||
}
|
||||
else
|
||||
{
|
||||
mSelectedFeatures = mSource->mFeatures.keys();
|
||||
}
|
||||
|
||||
mFeatureIterator = mSelectedFeatures.constBegin();
|
||||
@ -164,7 +162,7 @@ QgsWFSFeatureSource::~QgsWFSFeatureSource()
|
||||
|
||||
QgsFeatureIterator QgsWFSFeatureSource::getFeatures( const QgsFeatureRequest& request )
|
||||
{
|
||||
if ( request.filterType() == QgsFeatureRequest::FilterRect )
|
||||
if ( !request.filterRect().isNull() )
|
||||
emit extentRequested( request.filterRect() );
|
||||
return QgsFeatureIterator( new QgsWFSFeatureIterator( this, false, request ) );
|
||||
}
|
||||
|
@ -72,6 +72,15 @@ class ProviderTestCase(object):
|
||||
features = [f['pk'] for f in self.provider.getFeatures(QgsFeatureRequest().setFilterRect(extent))]
|
||||
assert set(features) == set([2L, 4L]), 'Got {} instead'.format(features)
|
||||
|
||||
def testRectAndExpression(self):
|
||||
extent = QgsRectangle(-70, 67, -60, 80)
|
||||
result = set([f['pk'] for f in self.provider.getFeatures(
|
||||
QgsFeatureRequest()
|
||||
.setFilterExpression('"cnt">200')
|
||||
.setFilterRect(extent))])
|
||||
expected=[4L]
|
||||
assert set(expected) == result, 'Expected {} and got {} when testing for combination of filterRect and expression'.format(set(expected), result)
|
||||
|
||||
def testMinValue(self):
|
||||
assert self.provider.minimumValue(1) == -200
|
||||
assert self.provider.minimumValue(2) == 'Apple'
|
||||
|
Loading…
x
Reference in New Issue
Block a user