Skip to content

Commit

Permalink
Merge pull request #5554 from pblottiere/bugfix_virtuallayer
Browse files Browse the repository at this point in the history
[bugfix] Fixes #16798 FilterFid feature requests with virtual layers
  • Loading branch information
pblottiere committed Nov 15, 2017
2 parents bd30e12 + b5317c5 commit 9f0985f
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 2 deletions.
28 changes: 26 additions & 2 deletions src/providers/virtual/qgsvirtuallayerfeatureiterator.cpp
Expand Up @@ -63,6 +63,7 @@ QgsVirtualLayerFeatureIterator::QgsVirtualLayerFeatureIterator( QgsVirtualLayerF
QString tableName = mSource->mTableName;

QStringList wheres;
QString offset;
QString subset = mSource->mSubset;
if ( !subset.isNull() )
{
Expand Down Expand Up @@ -105,6 +106,16 @@ QgsVirtualLayerFeatureIterator::QgsVirtualLayerFeatureIterator( QgsVirtualLayerF
wheres << values;
}
}
else
{
if ( request.filterType() == QgsFeatureRequest::FilterFid )
{
if ( request.filterFid() >= 0 )
offset = QStringLiteral( " LIMIT 1 OFFSET %1" ).arg( request.filterFid() );
else // never return a feature if the id is negative
offset = QStringLiteral( " LIMIT 0" );
}
}

if ( request.flags() & QgsFeatureRequest::SubsetOfAttributes )
{
Expand Down Expand Up @@ -150,7 +161,14 @@ QgsVirtualLayerFeatureIterator::QgsVirtualLayerFeatureIterator( QgsVirtualLayerF
}
else
{
columns = QStringLiteral( "0" );
if ( request.filterType() == QgsFeatureRequest::FilterFid )
{
columns = QString::number( request.filterFid() );
}
else
{
columns = QStringLiteral( "0" );
}
}
Q_FOREACH ( int i, mAttributes )
{
Expand All @@ -173,6 +191,11 @@ QgsVirtualLayerFeatureIterator::QgsVirtualLayerFeatureIterator( QgsVirtualLayerF
mSqlQuery += " WHERE " + wheres.join( QStringLiteral( " AND " ) );
}

if ( !offset.isEmpty() )
{
mSqlQuery += offset;
}

mQuery.reset( new Sqlite::Query( mSource->mSqlite, mSqlQuery ) );

mFid = 0;
Expand Down Expand Up @@ -230,7 +253,8 @@ bool QgsVirtualLayerFeatureIterator::fetchFeature( QgsFeature &feature )

feature.setFields( mSource->mFields, /* init */ true );

if ( mSource->mDefinition.uid().isNull() )
if ( mSource->mDefinition.uid().isNull() &&
mRequest.filterType() != QgsFeatureRequest::FilterFid )
{
// no id column => autoincrement
feature.setId( mFid++ );
Expand Down
40 changes: 40 additions & 0 deletions tests/src/python/test_provider_virtual.py
Expand Up @@ -85,6 +85,46 @@ def tearDown(self):
"""Run after each test."""
pass

def test_filterfid_crossjoin(self):
l0 = QgsVectorLayer(os.path.join(self.testDataDir, "france_parts.shp"), "france_parts", "ogr")
self.assertTrue(l0.isValid())
QgsProject.instance().addMapLayer(l0)

l1 = QgsVectorLayer(os.path.join(self.testDataDir, "points.shp"), "points", "ogr")
self.assertTrue(l1.isValid())
QgsProject.instance().addMapLayer(l1)

# cross join
query = toPercent("SELECT * FROM france_parts,points")
vl = QgsVectorLayer("?query=%s" % query, "tt", "virtual")

self.assertEqual(vl.featureCount(), l0.featureCount() * l1.featureCount())

# test with FilterFid requests
f = next(vl.getFeatures(QgsFeatureRequest().setFilterFid(0)))
idx = f.fields().indexOf('Class')
self.assertEqual(f.id(), 0)
self.assertEqual(f.attributes()[idx], 'Jet')

f = next(vl.getFeatures(QgsFeatureRequest().setFilterFid(5)))
self.assertEqual(f.id(), 5)
self.assertEqual(f.attributes()[idx], 'Biplane')

# test with FilterFid requests
fit = vl.getFeatures(QgsFeatureRequest().setFilterFids([0, 3, 5]))

f = next(fit)
self.assertEqual(f.id(), 0)
self.assertEqual(f.attributes()[idx], 'Jet')

f = next(fit)
self.assertEqual(f.id(), 3)
self.assertEqual(f.attributes()[idx], 'Jet')

f = next(fit)
self.assertEqual(f.id(), 5)
self.assertEqual(f.attributes()[idx], 'Biplane')

def test_CsvNoGeometry(self):
l1 = QgsVectorLayer(QUrl.fromLocalFile(os.path.join(self.testDataDir, "delimitedtext/test.csv")).toString() + "?type=csv&geomType=none&subsetIndex=no&watchFile=no", "test", "delimitedtext", QgsVectorLayer.LayerOptions(False))
self.assertEqual(l1.isValid(), True)
Expand Down

0 comments on commit 9f0985f

Please sign in to comment.