Skip to content

Commit 5e30831

Browse files
committed
QgsFeatureRequest::NoGeometry is optional for non-geometry-layers
1 parent 3d2814f commit 5e30831

11 files changed

+53
-48
lines changed

src/core/qgsfeaturerequest.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class CORE_EXPORT QgsFeatureRequest
5959
enum Flag
6060
{
6161
NoFlags = 0,
62-
NoGeometry = 1, //!< Do not fetch geometry
62+
NoGeometry = 1, //!< Geometry is not required. It may still be returned if e.g. required for a filter condition.
6363
SubsetOfAttributes = 2, //!< Fetch only a subset of attributes (setSubsetOfAttributes sets this flag)
6464
ExactIntersect = 4 //!< Use exact geometry intersection (slower) instead of bounding boxes
6565
};
@@ -68,7 +68,7 @@ class CORE_EXPORT QgsFeatureRequest
6868
enum FilterType
6969
{
7070
FilterNone, //!< No filter is applied
71-
FilterRect, //!< Filter using a rectangle
71+
FilterRect, //!< Filter using a rectangle, no need to set NoGeometry
7272
FilterFid, //!< Filter using feature ID
7373
FilterExpression, //!< Filter using expression
7474
FilterFids //!< Filter using feature ID's
@@ -117,8 +117,8 @@ class CORE_EXPORT QgsFeatureRequest
117117

118118
//! Set a subset of attributes by names that will be fetched
119119
QgsFeatureRequest& setSubsetOfAttributes( const QStringList& attrNames, const QgsFields& fields );
120-
121-
/**
120+
121+
/**
122122
* Check if a feature is accepted by this requests filter
123123
*
124124
* @param feature The feature which will be tested

src/providers/delimitedtext/qgsdelimitedtextfeatureiterator.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ QgsDelimitedTextFeatureIterator::QgsDelimitedTextFeatureIterator( QgsDelimitedTe
3636

3737
// Does the layer have geometry - will revise later to determine if we actually need to
3838
// load it.
39-
mLoadGeometry = P->mGeomRep != QgsDelimitedTextProvider::GeomNone;
39+
bool hasGeometry = P->mGeomRep != QgsDelimitedTextProvider::GeomNone;
4040

4141
// Does the layer have an explicit or implicit subset (implicit subset is if we have geometry which can
4242
// be invalid)
@@ -59,8 +59,7 @@ QgsDelimitedTextFeatureIterator::QgsDelimitedTextFeatureIterator( QgsDelimitedTe
5959
// requesting no geometry? Have preserved current logic of ignoring spatial filter
6060
// if not requesting geometry.
6161

62-
else if ( request.filterType() == QgsFeatureRequest::FilterRect && mLoadGeometry
63-
&& !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) )
62+
else if ( request.filterType() == QgsFeatureRequest::FilterRect && hasGeometry )
6463
{
6564
QgsDebugMsg( "Configuring for rectangle select" );
6665
mTestGeometry = true;
@@ -114,14 +113,23 @@ QgsDelimitedTextFeatureIterator::QgsDelimitedTextFeatureIterator( QgsDelimitedTe
114113
QgsDebugMsg( "File will be scanned for desired features" );
115114
}
116115

117-
// If the request does not require geometry, can we avoid loading it?
118-
// We need it if we are testing geometry (ie spatial filter), or
119-
// if testing the subset expression, and it uses geometry.
120-
if ( mRequest.flags() & QgsFeatureRequest::NoGeometry &&
121-
! mTestGeometry &&
122-
!( mTestSubset && P->mSubsetExpression->needsGeometry() ) )
116+
// If the layer has geometry, do we really need to load it?
117+
// We need it if it is asked for explicitly in the request,
118+
// if we are testing geometry (ie spatial filter), or
119+
// if testing the subset expression.
120+
if ( hasGeometry
121+
&& (
122+
!( mRequest.flags() & QgsFeatureRequest::NoGeometry )
123+
|| mTestGeometry
124+
|| ( mTestSubset && P->mSubsetExpression->needsGeometry() )
125+
)
126+
)
123127
{
124-
QgsDebugMsg( "Feature geometries not required" );
128+
mLoadGeometry = true;
129+
}
130+
else
131+
{
132+
QgsDebugMsgLevel( "Feature geometries not required", 4 );
125133
mLoadGeometry = false;
126134
}
127135

src/providers/mssql/qgsmssqlfeatureiterator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ void QgsMssqlFeatureIterator::BuildStatement( const QgsFeatureRequest& request )
122122
++fieldCount;
123123
}
124124
// get geometry col
125-
if ( request.flags() != QgsFeatureRequest::NoGeometry && !mProvider->mGeometryColName.isEmpty() )
125+
if ( !( request.flags() & QgsFeatureRequest::NoGeometry ) && !mProvider->mGeometryColName.isEmpty() )
126126
{
127127
if ( fieldCount != 0 )
128128
mStatement += ",";

src/providers/ogr/qgsogrfeatureiterator.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ QgsOgrFeatureIterator::~QgsOgrFeatureIterator()
8989

9090
void QgsOgrFeatureIterator::ensureRelevantFields()
9191
{
92-
bool needGeom = ( mRequest.filterType() == QgsFeatureRequest::FilterRect ) || !( mRequest.flags() & QgsFeatureRequest::NoGeometry );
92+
mFetchGeometry = ( mRequest.filterType() == QgsFeatureRequest::FilterRect ) || !( mRequest.flags() & QgsFeatureRequest::NoGeometry );
9393
QgsAttributeList attrs = ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) ? mRequest.subsetOfAttributes() : P->attributeIndexes();
94-
P->setRelevantFields( needGeom, attrs );
94+
P->setRelevantFields( mFetchGeometry, attrs );
9595
P->mRelevantFieldsForNextFeature = true;
9696
}
9797

@@ -225,10 +225,9 @@ bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature )
225225
feature.initAttributes( P->fields().count() );
226226
feature.setFields( &P->mAttributeFields ); // allow name-based attribute lookups
227227

228-
bool fetchGeom = !( mRequest.flags() & QgsFeatureRequest::NoGeometry );
229228
bool useIntersect = mRequest.flags() & QgsFeatureRequest::ExactIntersect;
230229
bool geometryTypeFilter = P->mOgrGeometryTypeFilter != wkbUnknown;
231-
if ( fetchGeom || useIntersect || geometryTypeFilter )
230+
if ( mFetchGeometry || useIntersect || geometryTypeFilter )
232231
{
233232
OGRGeometryH geom = OGR_F_GetGeometryRef( fet );
234233

@@ -248,7 +247,7 @@ bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature )
248247
}
249248
}
250249

251-
if ( !fetchGeom )
250+
if ( !mFetchGeometry )
252251
{
253252
feature.setGeometry( 0 );
254253
}

src/providers/ogr/qgsogrfeatureiterator.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ class QgsOgrFeatureIterator : public QgsAbstractFeatureIterator
5353
OGRLayerH ogrLayer;
5454

5555
bool mSubsetStringSet;
56+
57+
//! Set to true, if geometry is in the requested columns
58+
bool mFetchGeometry;
5659
};
5760

5861

src/providers/postgres/qgspostgresfeatureiterator.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ bool QgsPostgresFeatureIterator::fetchFeature( QgsFeature& feature )
149149
}
150150

151151
// Now return the next feature from the queue
152-
if ( mRequest.flags() & QgsFeatureRequest::NoGeometry )
152+
if ( !mFetchGeometry )
153153
{
154154
feature.setGeometryAndOwnership( 0, 0 );
155155
}
@@ -264,18 +264,13 @@ QString QgsPostgresFeatureIterator::whereClauseRect()
264264

265265
bool QgsPostgresFeatureIterator::declareCursor( const QString& whereClause )
266266
{
267-
bool fetchGeometry = !( mRequest.flags() & QgsFeatureRequest::NoGeometry );
268-
if ( fetchGeometry && P->mGeometryColumn.isNull() )
269-
{
270-
QgsMessageLog::logMessage( QObject::tr( "Trying to fetch geometry on a layer without geometry." ), QObject::tr( "PostgreSQL" ) );
271-
return false;
272-
}
267+
mFetchGeometry = !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) && !P->mGeometryColumn.isNull();
273268

274269
try
275270
{
276271
QString query = "SELECT ", delim = "";
277272

278-
if ( fetchGeometry )
273+
if ( mFetchGeometry )
279274
{
280275
query += QString( "%1(%2%3,'%4')" )
281276
.arg( P->mConnectionRO->majorVersion() < 2 ? "asbinary" : "st_asbinary" )
@@ -356,7 +351,7 @@ bool QgsPostgresFeatureIterator::getFeature( QgsPostgresResult &queryResult, int
356351

357352
int col = 0;
358353

359-
if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) )
354+
if ( mFetchGeometry )
360355
{
361356
int returnedLength = ::PQgetlength( queryResult.result(), row, col );
362357
if ( returnedLength > 0 )

src/providers/postgres/qgspostgresfeatureiterator.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,12 @@ class QgsPostgresFeatureIterator : public QgsAbstractFeatureIterator
5858
//! Maximal size of the feature queue
5959
int mFeatureQueueSize;
6060

61-
//!< Number of retrieved features
61+
//! Number of retrieved features
6262
int mFetched;
6363

64+
//! Set to true, if geometry is in the requested columns
65+
bool mFetchGeometry;
66+
6467
static const int sFeatureQueueSize;
6568

6669
};

src/providers/spatialite/qgsspatialitefeatureiterator.cpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,6 @@ bool QgsSpatiaLiteFeatureIterator::close()
144144

145145
bool QgsSpatiaLiteFeatureIterator::prepareStatement( QString whereClause )
146146
{
147-
if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) && P->mGeometryColumn.isNull() )
148-
{
149-
QgsMessageLog::logMessage( QObject::tr( "Trying to fetch geometry on a layer without geometry." ), QObject::tr( "SpatiaLite" ) );
150-
return false;
151-
}
152-
153147
try
154148
{
155149
QString sql = QString( "SELECT %1" ).arg( quotedPrimaryKey() );
@@ -174,7 +168,7 @@ bool QgsSpatiaLiteFeatureIterator::prepareStatement( QString whereClause )
174168
}
175169
}
176170

177-
if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) )
171+
if ( mFetchGeometry )
178172
{
179173
sql += QString( ", AsBinary(%1)" ).arg( P->quotedIdentifier( P->mGeometryColumn ) );
180174
mGeomColIdx = colIdx;
@@ -284,7 +278,7 @@ QString QgsSpatiaLiteFeatureIterator::fieldName( const QgsField& fld )
284278

285279
bool QgsSpatiaLiteFeatureIterator::getFeature( sqlite3_stmt *stmt, QgsFeature &feature )
286280
{
287-
bool fetchGeometry = !( mRequest.flags() & QgsFeatureRequest::NoGeometry );
281+
mFetchGeometry = !( mRequest.flags() & QgsFeatureRequest::NoGeometry );
288282
bool subsetAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes;
289283

290284
int ret = sqlite3_step( stmt );
@@ -301,7 +295,7 @@ bool QgsSpatiaLiteFeatureIterator::getFeature( sqlite3_stmt *stmt, QgsFeature &f
301295
}
302296

303297
// one valid row has been fetched from the result set
304-
if ( !fetchGeometry )
298+
if ( !mFetchGeometry )
305299
{
306300
// no geometry was required
307301
feature.setGeometryAndOwnership( 0, 0 );
@@ -321,7 +315,7 @@ bool QgsSpatiaLiteFeatureIterator::getFeature( sqlite3_stmt *stmt, QgsFeature &f
321315
QgsDebugMsgLevel( QString( "fid=%1" ).arg( fid ), 3 );
322316
feature.setFeatureId( fid );
323317
}
324-
else if ( fetchGeometry && ic == mGeomColIdx )
318+
else if ( mFetchGeometry && ic == mGeomColIdx )
325319
{
326320
getFeatureGeometry( stmt, ic, feature );
327321
}

src/providers/spatialite/qgsspatialitefeatureiterator.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ class QgsSpatiaLiteFeatureIterator : public QgsAbstractFeatureIterator
6363
/** geometry column index used when fetching geometry */
6464
int mGeomColIdx;
6565

66+
//! Set to true, if geometry is in the requested columns
67+
bool mFetchGeometry;
68+
6669
};
6770

6871
#endif // QGSSPATIALITEFEATUREITERATOR_H

src/providers/sqlanywhere/qgssqlanywherefeatureiterator.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ bool QgsSqlAnywhereFeatureIterator::nextFeature( QgsFeature& feature, SqlAnyStat
106106
{
107107
feature.setValid( false );
108108

109-
bool fetchGeometry = !( mRequest.flags() & QgsFeatureRequest::NoGeometry );
109+
mFetchGeometry = !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) && !P->mGeometryColumn.isNull();
110110
bool subsetAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes;
111111

112112
if ( mClosed )
@@ -130,7 +130,7 @@ bool QgsSqlAnywhereFeatureIterator::nextFeature( QgsFeature& feature, SqlAnyStat
130130
if ( !ok )
131131
return false;
132132

133-
if ( !fetchGeometry )
133+
if ( !mFetchGeometry )
134134
feature.setGeometryAndOwnership( 0, 0 );
135135

136136
int numAttributes = P->fields().count(); // also used later for sanity check
@@ -151,7 +151,7 @@ bool QgsSqlAnywhereFeatureIterator::nextFeature( QgsFeature& feature, SqlAnyStat
151151
QgsDebugMsgLevel( QString( "pid=%1" ).arg( id ), 3 );
152152
feature.setFeatureId( id );
153153
}
154-
else if ( i == 1 && fetchGeometry )
154+
else if ( i == 1 && mFetchGeometry )
155155
{
156156
// second column contains QKB geometry value
157157
ok = stmt->getColumn( i, &geom );
@@ -174,7 +174,7 @@ bool QgsSqlAnywhereFeatureIterator::nextFeature( QgsFeature& feature, SqlAnyStat
174174

175175
// Sanity check before setting the attribute value
176176
if ( colidx - 1 == i // First column is always pk, so colidx should be at least 1 behind
177-
|| ( colidx - 1 == i - 1 && fetchGeometry ) // if fetchGeometry is true, colidx should be 2 behind
177+
|| ( colidx - 1 == i - 1 && mFetchGeometry ) // if fetchGeometry is true, colidx should be 2 behind
178178
|| attrIndex >= numAttributes ) // index should always be less than the count
179179
{
180180
SaDebugMsg( QString( "Error retrieving feature column %1 with attribute index %2" ).arg( i ).arg( attrIndex ) );
@@ -220,9 +220,6 @@ bool
220220
QgsSqlAnywhereFeatureIterator::prepareStatement( QString whereClause )
221221
// adapted from QgsSpatialLiteFeatureIterator::prepareStatement
222222
{
223-
if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) && P->mGeometryColumn.isNull() )
224-
return false;
225-
226223
if ( !P->ensureConnRO() )
227224
{
228225
SaDebugMsg( "No read-only database connection." );
@@ -232,7 +229,7 @@ QgsSqlAnywhereFeatureIterator::prepareStatement( QString whereClause )
232229
QString sql = QString( "SELECT %1" ).arg( quotedPrimaryKey() ); // Column 0 is primary key
233230

234231
// Column 1 is geometry, if applicable
235-
if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) )
232+
if ( mFetchGeometry )
236233
{
237234
sql += QString( ", %1 .ST_AsBinary('WKB(Version=1.1;endian=%2)') " )
238235
.arg( P->mGeometryColumn )

src/providers/sqlanywhere/qgssqlanywherefeatureiterator.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ class QgsSqlAnywhereFeatureIterator : public QgsAbstractFeatureIterator
6161

6262
QgsRectangle mStmtRect;
6363

64+
//! Set to true, if geometry is in the requested columns
65+
bool mFetchGeometry;
66+
6467
};
6568

6669
#endif // QGSSQLANYWHEREFEATUREITERATOR_H

0 commit comments

Comments
 (0)