From 8843de88c761ab9bed8f12a21ee5a37e5c78aed7 Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Tue, 18 Oct 2016 10:45:53 +0200 Subject: [PATCH] Fix ogrLayerName handling of PostgreSQL dataset URIs Also document "uri" parameter semantic, and add more tests. See for background https://lists.osgeo.org/pipermail/qgis-developer/2016-October/045311.html REF #15698 --- python/plugins/processing/tests/ToolsTest.py | 12 +++++- python/plugins/processing/tools/vector.py | 45 ++++++++++++++++---- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/python/plugins/processing/tests/ToolsTest.py b/python/plugins/processing/tests/ToolsTest.py index 4baeb49c66fc..8d015d70a39a 100644 --- a/python/plugins/processing/tests/ToolsTest.py +++ b/python/plugins/processing/tests/ToolsTest.py @@ -70,33 +70,41 @@ def test_ogrLayerName(self): def linkTestfile(f, t): os.link(os.path.join(dataFolder, f), os.path.join(tmpdir, t)) + # URI from OGR provider linkTestfile('geom_data.csv', 'a.csv') name = vector.ogrLayerName(tmpdir) self.assertEqual(name, 'a') + # URI from OGR provider linkTestfile('wkt_data.csv', 'b.csv') name = vector.ogrLayerName(tmpdir + '|layerid=0') self.assertEqual(name, 'a') name = vector.ogrLayerName(tmpdir + '|layerid=1') self.assertEqual(name, 'b') + # URI from OGR provider name = vector.ogrLayerName(tmpdir + '|layerid=2') self.assertEqual(name, 'invalid-layerid') + # URI from OGR provider name = vector.ogrLayerName(tmpdir + '|layername=f') self.assertEqual(name, 'f') # layername takes precedence + # URI from OGR provider name = vector.ogrLayerName(tmpdir + '|layerid=0|layername=f2') self.assertEqual(name, 'f2') # layername takes precedence + # URI from OGR provider name = vector.ogrLayerName(tmpdir + '|layername=f2|layerid=0') self.assertEqual(name, 'f2') # layername takes precedence + # URI from Sqlite provider name = vector.ogrLayerName('dbname=\'/tmp/x.sqlite\' table="t" (geometry) sql=') self.assertEqual(name, 't') - name = vector.ogrLayerName('dbname=\'/tmp/x.sqlite\' table="s.t" (geometry) sql=') - self.assertEqual(name, 's.t') + # URI from PostgreSQL provider + name = vector.ogrLayerName('port=5493 sslmode=disable key=\'edge_id\' srid=0 type=LineString table="city_data"."edge" (geom) sql=') + self.assertEqual(name, 'city_data.edge') def testFeatures(self): ProcessingConfig.initialize() diff --git a/python/plugins/processing/tools/vector.py b/python/plugins/processing/tools/vector.py index 8a7e7e6ecff2..bd52ea399dd5 100644 --- a/python/plugins/processing/tools/vector.py +++ b/python/plugins/processing/tools/vector.py @@ -532,16 +532,43 @@ def ogrConnectionString(uri): return '"' + ogrstr + '"' +# +# The uri parameter is an URI from any QGIS provider, +# so could have different formats. +# Example formats: +# +# -- PostgreSQL provider +# port=5493 sslmode=disable key='edge_id' srid=0 type=LineString table="city_data"."edge" (geom) sql= +# +# -- Spatialite provider +# dbname='/tmp/x.sqlite' table="t" (geometry) sql=' +# +# -- OGR provider (single-layer directory) +# /tmp/x.gdb +# +# -- OGR provider (multi-layer directory) +# /tmp/x.gdb|layerid=1 +# +# -- OGR provider (multi-layer directory) +# /tmp/x.gdb|layername=thelayer +# def ogrLayerName(uri): - if 'host' in uri: - regex = re.compile('table="(.+?)\.(.+?)"') - r = regex.search(uri) - return '"' + r.groups()[0] + '.' + r.groups()[1] + '"' - elif 'dbname' in uri: - regex = re.compile('table="(.+?)"') - r = regex.search(uri) - return r.groups()[0] - elif 'layername' in uri: + + # handle URIs of database providers + if ' table=' in uri: + # Matches table="schema"."table" + re_table_schema = re.compile(' table="([^"]*)"\."([^"]*)"') + r = re_table_schema.search(uri) + if r: + return r.groups()[0] + '.' + r.groups()[1] + # Matches table="table" + re_table = re.compile(' table="([^"]*)"') + r = re_table.search(uri) + if r: + return r.groups()[0] + + # handle URIs of OGR provider with explicit layername + if 'layername' in uri: regex = re.compile('(layername=)([^|]*)') r = regex.search(uri) return r.groups()[1]