Skip to content
Permalink
Browse files

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 aa413b67a0834360c1a8fce02f5da54c0949cca1
Showing with 46 additions and 11 deletions.
  1. +10 −2 python/plugins/processing/tests/ToolsTest.py
  2. +36 −9 python/plugins/processing/tools/vector.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()
@@ -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]

0 comments on commit aa413b6

Please sign in to comment.
You can’t perform that action at this time.