Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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
  • Loading branch information
strk committed Oct 18, 2016
1 parent 71bfa1d commit aa413b6
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 11 deletions.
12 changes: 10 additions & 2 deletions python/plugins/processing/tests/ToolsTest.py
Expand Up @@ -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()
Expand Down
45 changes: 36 additions & 9 deletions python/plugins/processing/tools/vector.py
Expand Up @@ -512,16 +512,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]
Expand Down

0 comments on commit aa413b6

Please sign in to comment.