Fix extraction of ogr LayerName from multi-layer dataset URIs

Adds supports for "layerid" when present.
Drop special handling for "table=" portions found in URI,
making the code more generic.

Includes testcase.

Fixes #15698 - import geodatabase to postgis via processing
This commit is contained in:
Sandro Santilli 2016-10-14 15:11:02 +02:00
parent 60b4b4db18
commit 6c5364186d
2 changed files with 78 additions and 14 deletions

View File

@ -31,11 +31,67 @@ from processing.tools import vector
from qgis.core import (QgsVectorLayer, QgsFeatureRequest) from qgis.core import (QgsVectorLayer, QgsFeatureRequest)
from processing.core.ProcessingConfig import ProcessingConfig from processing.core.ProcessingConfig import ProcessingConfig
import os.path
import errno
import shutil
dataFolder = os.path.join(os.path.dirname(__file__), '../../../../tests/testdata/')
tmpBaseFolder = os.path.join(os.sep, 'tmp', 'qgis_test', str(os.getpid()))
def mkDirP(path):
try:
os.makedirs(path)
except OSError as exc:
if exc.errno == errno.EEXIST and os.path.isdir(path):
pass
else:
raise
start_app() start_app()
class VectorTest(unittest.TestCase): class VectorTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
mkDirP(tmpBaseFolder)
@classmethod
def tearDownClass(cls):
shutil.rmtree(tmpBaseFolder)
pass
# See http://hub.qgis.org/issues/15698
def test_ogrLayerName(self):
tmpdir = os.path.join(tmpBaseFolder, 'ogrLayerName')
os.mkdir(tmpdir)
def linkTestfile(f, t):
os.link(os.path.join(dataFolder, f), os.path.join(tmpdir, t))
linkTestfile('geom_data.csv', 'a.csv')
name = vector.ogrLayerName(tmpdir)
self.assertEqual(name, 'a')
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')
name = vector.ogrLayerName(tmpdir + '|layerid=2')
self.assertEqual(name, 'invalid-layerid')
name = vector.ogrLayerName(tmpdir + '|layername=f')
self.assertEqual(name, 'f') # layername takes precedence
name = vector.ogrLayerName(tmpdir + '|layerid=0|layername=f2')
self.assertEqual(name, 'f2') # layername takes precedence
name = vector.ogrLayerName(tmpdir + '|layername=f2|layerid=0')
self.assertEqual(name, 'f2') # layername takes precedence
def testFeatures(self): def testFeatures(self):
ProcessingConfig.initialize() ProcessingConfig.initialize()

View File

@ -41,6 +41,8 @@ import io
import psycopg2 import psycopg2
from osgeo import ogr
from qgis.PyQt.QtCore import QVariant, QSettings from qgis.PyQt.QtCore import QVariant, QSettings
from qgis.core import (Qgis, QgsFields, QgsField, QgsGeometry, QgsRectangle, QgsWkbTypes, from qgis.core import (Qgis, QgsFields, QgsField, QgsGeometry, QgsRectangle, QgsWkbTypes,
QgsSpatialIndex, QgsMapLayerRegistry, QgsMapLayer, QgsVectorLayer, QgsSpatialIndex, QgsMapLayerRegistry, QgsMapLayer, QgsVectorLayer,
@ -531,20 +533,26 @@ def ogrConnectionString(uri):
def ogrLayerName(uri): def ogrLayerName(uri):
if 'host' in uri: fields = uri.split('|')
regex = re.compile('(table=")(.+?)(\.)(.+?)"') ogruri = fields[0]
r = regex.search(uri) fields = fields[1:]
return '"' + r.groups()[1] + '.' + r.groups()[3] + '"' layerid = 0
elif 'dbname' in uri: for f in fields:
regex = re.compile('(table=")(.+?)"') if f.startswith('layername='):
r = regex.search(uri) # Name encoded in uri, nothing more needed
return r.groups()[1] return f.split('=')[1]
elif 'layername' in uri: if f.startswith('layerid='):
regex = re.compile('(layername=)(.*)') layerid = int(f.split('=')[1])
r = regex.search(uri) # Last layerid= takes precedence, to allow of layername to
return r.groups()[1] # take precedence
else: ds = ogr.Open(ogruri)
return os.path.basename(os.path.splitext(uri)[0]) if not ds:
return "invalid-uri"
ly = ds.GetLayer(layerid)
if not ly:
return "invalid-layerid"
name = ly.GetName()
return name
class VectorWriter(object): class VectorWriter(object):