Skip to content
Permalink
Browse files
If OGR uri specifies an explicit layer, only consider this layer
when querying sublayers
  • Loading branch information
nyalldawson committed Jul 12, 2021
1 parent 61c8421 commit 79b622f14a32ef8f52ecc186843c99039841838e
Showing with 88 additions and 1 deletion.
  1. +27 −1 src/core/providers/ogr/qgsogrprovidermetadata.cpp
  2. +61 −0 tests/src/python/test_provider_ogr.py
@@ -1033,8 +1033,16 @@ QList<QgsProviderSublayerDetails> QgsOgrProviderMetadata::querySublayers( const
{
QStringList options { QStringLiteral( "@LIST_ALL_TABLES=YES" ) };

const QVariantMap uriParts = decodeUri( uri );
const QString originalUriLayerName = uriParts.value( QStringLiteral( "layerName" ) ).toString();
int layerId = 0;
bool originalUriLayerIdWasSpecified = false;
const int uriLayerId = uriParts.value( QStringLiteral( "layerId" ) ).toInt( &originalUriLayerIdWasSpecified );
if ( originalUriLayerIdWasSpecified )
layerId = uriLayerId;

QString errCause;
QgsOgrLayerUniquePtr firstLayer = QgsOgrProviderUtils::getLayer( uri, false, options, 0, errCause, true );
QgsOgrLayerUniquePtr firstLayer = QgsOgrProviderUtils::getLayer( uriParts.value( QStringLiteral( "path" ) ).toString(), false, options, layerId, errCause, true );
if ( !firstLayer )
return {};

@@ -1107,6 +1115,24 @@ QList<QgsProviderSublayerDetails> QgsOgrProviderMetadata::querySublayers( const
res[i].setUri( encodeUri( parts ) );
}

if ( !originalUriLayerName.isEmpty() )
{
// remove non-matching, unwanted layers
res.erase( std::remove_if( res.begin(), res.end(), [ = ]( const QgsProviderSublayerDetails & sublayer )
{
return sublayer.name() != originalUriLayerName;
} ), res.end() );
}

if ( originalUriLayerIdWasSpecified )
{
// remove non-matching, unwanted layers
res.erase( std::remove_if( res.begin(), res.end(), [ = ]( const QgsProviderSublayerDetails & sublayer )
{
return sublayer.layerNumber() != uriLayerId;
} ), res.end() );
}

return res;
}

@@ -1587,6 +1587,67 @@ def test_provider_sublayer_details(self):
self.assertEqual(res[1].featureCount(), 6)
self.assertEqual(res[1].geometryColumnName(), 'geom')

# geopackage with two layers, but specific layer is requested in uri
res = metadata.querySublayers(os.path.join(TEST_DATA_DIR, "mixed_layers.gpkg") + '|layerid=0')
self.assertEqual(len(res), 1)
self.assertEqual(res[0].layerNumber(), 0)
self.assertEqual(res[0].name(), "points")
self.assertEqual(res[0].description(), "")
self.assertEqual(res[0].uri(), "{}/mixed_layers.gpkg|layername=points".format(TEST_DATA_DIR))
self.assertEqual(res[0].providerKey(), "ogr")
self.assertEqual(res[0].type(), QgsMapLayerType.VectorLayer)
self.assertEqual(res[0].featureCount(), Qgis.FeatureCountState.Uncounted)
self.assertEqual(res[0].wkbType(), QgsWkbTypes.Point)
self.assertEqual(res[0].geometryColumnName(), 'geometry')
vl = res[0].toLayer(options)
self.assertTrue(vl.isValid())
self.assertEqual(vl.wkbType(), QgsWkbTypes.Point)

res = metadata.querySublayers(os.path.join(TEST_DATA_DIR, "mixed_layers.gpkg") + '|layerid=1')
self.assertEqual(len(res), 1)
self.assertEqual(res[0].layerNumber(), 1)
self.assertEqual(res[0].name(), "lines")
self.assertEqual(res[0].description(), "")
self.assertEqual(res[0].uri(), "{}/mixed_layers.gpkg|layername=lines".format(TEST_DATA_DIR))
self.assertEqual(res[0].providerKey(), "ogr")
self.assertEqual(res[0].type(), QgsMapLayerType.VectorLayer)
self.assertEqual(res[0].featureCount(), Qgis.FeatureCountState.Uncounted)
self.assertEqual(res[0].wkbType(), QgsWkbTypes.MultiLineString)
self.assertEqual(res[0].geometryColumnName(), 'geom')
vl = res[0].toLayer(options)
self.assertTrue(vl.isValid())
self.assertEqual(vl.wkbType(), QgsWkbTypes.MultiLineString)

res = metadata.querySublayers(os.path.join(TEST_DATA_DIR, "mixed_layers.gpkg") + '|layername=points')
self.assertEqual(len(res), 1)
self.assertEqual(res[0].layerNumber(), 0)
self.assertEqual(res[0].name(), "points")
self.assertEqual(res[0].description(), "")
self.assertEqual(res[0].uri(), "{}/mixed_layers.gpkg|layername=points".format(TEST_DATA_DIR))
self.assertEqual(res[0].providerKey(), "ogr")
self.assertEqual(res[0].type(), QgsMapLayerType.VectorLayer)
self.assertEqual(res[0].featureCount(), Qgis.FeatureCountState.Uncounted)
self.assertEqual(res[0].wkbType(), QgsWkbTypes.Point)
self.assertEqual(res[0].geometryColumnName(), 'geometry')
vl = res[0].toLayer(options)
self.assertTrue(vl.isValid())
self.assertEqual(vl.wkbType(), QgsWkbTypes.Point)

res = metadata.querySublayers(os.path.join(TEST_DATA_DIR, "mixed_layers.gpkg") + '|layername=lines')
self.assertEqual(len(res), 1)
self.assertEqual(res[0].layerNumber(), 1)
self.assertEqual(res[0].name(), "lines")
self.assertEqual(res[0].description(), "")
self.assertEqual(res[0].uri(), "{}/mixed_layers.gpkg|layername=lines".format(TEST_DATA_DIR))
self.assertEqual(res[0].providerKey(), "ogr")
self.assertEqual(res[0].type(), QgsMapLayerType.VectorLayer)
self.assertEqual(res[0].featureCount(), Qgis.FeatureCountState.Uncounted)
self.assertEqual(res[0].wkbType(), QgsWkbTypes.MultiLineString)
self.assertEqual(res[0].geometryColumnName(), 'geom')
vl = res[0].toLayer(options)
self.assertTrue(vl.isValid())
self.assertEqual(vl.wkbType(), QgsWkbTypes.MultiLineString)

# layer with mixed geometry types - without resolving geometry types
res = metadata.querySublayers(os.path.join(TEST_DATA_DIR, "mixed_types.TAB"))
self.assertEqual(len(res), 1)

0 comments on commit 79b622f

Please sign in to comment.