From 31e20083dc9f01e6f2e31202b3a8718e92c2dd50 Mon Sep 17 00:00:00 2001 From: Julien Cabieces Date: Fri, 25 Sep 2020 00:37:33 +0200 Subject: [PATCH] [VirtualLayer] Catch exception while updating virtual layer stats Fixes #34378 --- .../virtual/qgsvirtuallayerprovider.cpp | 33 ++++++++++++------- tests/src/python/test_provider_virtual.py | 20 +++++++++++ 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/providers/virtual/qgsvirtuallayerprovider.cpp b/src/providers/virtual/qgsvirtuallayerprovider.cpp index c2f905dd9478..b2d34d05cca4 100644 --- a/src/providers/virtual/qgsvirtuallayerprovider.cpp +++ b/src/providers/virtual/qgsvirtuallayerprovider.cpp @@ -568,20 +568,30 @@ void QgsVirtualLayerProvider::updateStatistics() const .arg( hasGeometry ? QStringLiteral( ",Min(MbrMinX(%1)),Min(MbrMinY(%1)),Max(MbrMaxX(%1)),Max(MbrMaxY(%1))" ).arg( quotedColumn( mDefinition.geometryField() ) ) : QString(), mTableName, subset ); - Sqlite::Query q( mSqlite.get(), sql ); - if ( q.step() == SQLITE_ROW ) + + try { - mFeatureCount = q.columnInt64( 0 ); - if ( hasGeometry ) + Sqlite::Query q( mSqlite.get(), sql ); + if ( q.step() == SQLITE_ROW ) { - double x1, y1, x2, y2; - x1 = q.columnDouble( 1 ); - y1 = q.columnDouble( 2 ); - x2 = q.columnDouble( 3 ); - y2 = q.columnDouble( 4 ); - mExtent = QgsRectangle( x1, y1, x2, y2 ); + mFeatureCount = q.columnInt64( 0 ); + if ( hasGeometry ) + { + double x1, y1, x2, y2; + x1 = q.columnDouble( 1 ); + y1 = q.columnDouble( 2 ); + x2 = q.columnDouble( 3 ); + y2 = q.columnDouble( 4 ); + mExtent = QgsRectangle( x1, y1, x2, y2 ); + } + mCachedStatistics = true; } - mCachedStatistics = true; + } + catch ( std::runtime_error &e ) + { + pushError( tr( "Error while executing feature count request : %1" ).arg( e.what() ) ); + mFeatureCount = 0; + return; } } @@ -709,4 +719,3 @@ QGISEXTERN QgsProviderGuiMetadata *providerGuiMetadataFactory() return new QgsVirtualLayerProviderGuiMetadata(); } #endif - diff --git a/tests/src/python/test_provider_virtual.py b/tests/src/python/test_provider_virtual.py index 87d772e84ba1..af0538917fea 100644 --- a/tests/src/python/test_provider_virtual.py +++ b/tests/src/python/test_provider_virtual.py @@ -1187,6 +1187,26 @@ def test_subset_string(self): self.assertEqual(gpkg_virtual_layer.subsetString(), '"join_value" = \'twenty\'') self.assertEqual(gpkg_virtual_layer.featureCount(), 1) + def test_feature_count_on_error(self): + """Test that triggered exception while getting feature count on a badly defined + virtual layer is correctly caught (see https://github.com/qgis/QGIS/issues/34378)""" + + l1 = QgsVectorLayer(os.path.join(self.testDataDir, "france_parts.shp"), "france", "ogr", + QgsVectorLayer.LayerOptions(False)) + self.assertEqual(l1.isValid(), True) + QgsProject.instance().addMapLayer(l1) + + df = QgsVirtualLayerDefinition() + df.setQuery('select error') + + vl = QgsVectorLayer(df.toString(), "testq", "virtual") + self.assertEqual(vl.isValid(), False) + self.assertEqual(vl.featureCount(), 0) + ids = [f.id() for f in vl.getFeatures()] + self.assertEqual(len(ids), 0) + + QgsProject.instance().removeMapLayer(l1.id()) + if __name__ == '__main__': unittest.main()