Bug report #19938

Updated by Giovanni Manghi over 5 years ago

See also https://issues.qgis.org/issues/19938#note-4 for a better understanding of the issue.

*Original description:*

The GDAL/OGR vector geoprocessing algorithms do not work with GPKG, SQLite, FileGDB, (probably other formats), as input vector layer.

See the following error for GDAL "Buffer vector" alg. as example, with a GPKG input vector layer:

> Processing algorithm…
> Algorithm 'Buffer vectors' starting…
> Input parameters:
> { 'DISSOLVE' : False, 'DISTANCE' : 10, 'EXPLODE_COLLECTIONS' : False, 'FIELD' : None, 'GEOMETRY' : 'geometry', *'INPUT' : 'C:\\test\\demo\\test.gpkg|layername=points_layer'*, 'OPTIONS' : '', 'OUTPUT' : 'C:/Users/Andrea/AppData/Local/Temp/processing_a2e42c246f5c42e7b34ff0883d38d602/d685014df90f4511a2d43058c7d3cc2e/OUTPUT.shp' }
>
> GDAL command:
> ogr2ogr C:/Users/Andrea/AppData/Local/Temp/processing_a2e42c246f5c42e7b34ff0883d38d602/d685014df90f4511a2d43058c7d3cc2e/OUTPUT.shp *C:/Users/Andrea/AppData/Local/Temp/processing_a2e42c246f5c42e7b34ff0883d38d602/2e08c2dab752494ebc42763c1f331c53/INPUT.shp* -dialect sqlite -sql "SELECT ST_Buffer(geometry, 10.0) AS geometry, fid,field1 FROM *'points_layer'*" -f "ESRI Shapefile"
> GDAL command output:
> ERROR 1: In ExecuteSQL(): sqlite3_prepare_v2(SELECT ST_Buffer(geometry, 10.0) AS geometry, fid,field1 FROM 'points_layer'):
>
> *no such table: points_layer*

It seems that before the GDAL/OGR vector geoprocessing algs run their tasks, *every input layer contained in GPKG, SQLite, FileGDB, is converted in a temporary INPUT.SHP* shapefile which is used as new input layer for the ogr2ogr command.

This happens because in QgsProcessingUtils::convertToCompatibleFormat the layer suffix (QFileInfo.suffix()) for those layer types is something like:

<pre>
'gpkg|layername=points_layer'
</pre>

and this string does not match with any of the QgsVectorFileWriter.supportedFormatExtensions(), due to the presence of "|layername=points_layer", leading to always convert (translate) those types of layers in the temporary shapefile INPUT.SHP.
I don't know if this is a normal behaviour or a bug, but I think they can be normally used by ogr2ogr as input layer without conversion, provided we specify the right geometry column name.

If this is a bug, I think it could be fixed in QgsProcessingUtils::convertToCompatibleFormat just changing

<pre>
QFileInfo fi( vl->source() );
requiresTranslation = !compatibleFormats.contains( fi.suffix(), Qt::CaseInsensitive );
</pre>

with

<pre>
QFileInfo fi( vl->source() );
requiresTranslation = !compatibleFormats.contains( fi.suffix().split('|')[0], Qt::CaseInsensitive );
</pre>

Anyway, algorithms fail to properly build the sql statement: in fact if INPUT.SHP must be used as new input layer, then the table name after FROM should be 'INPUT' and not the original layer name 'points_layer'.

This problem could be fixed in https://github.com/qgis/QGIS/blob/master/python/plugins/processing/algs/gdal/GdalAlgorithm.py#L104-L109

<pre>
# parameter is a vector layer, with OGR data provider
# so extract selection if required
ogr_data_path = self.parameterAsCompatibleSourceLayerPath(parameters, parameter_name, context,
QgsVectorFileWriter.supportedFormatExtensions(),
feedback=feedback)
ogr_layer_name = GdalUtils.ogrLayerName(input_layer.dataProvider().dataSourceUri())
</pre>

where

<pre>
ogr_layer_name = GdalUtils.ogrLayerName(input_layer.dataProvider().dataSourceUri())
</pre>

should be

<pre>
ogr_layer_name = GdalUtils.ogrLayerName(ogr_data_path)
</pre>

This works for me, changing my local copy of GdalAlgorithm.py, but I cannot say if this is the right way to solve the problem or if it's possible to completely avoid the needing of convert GPKG, SQLite, FileGDB layers, and probably other formats, to a temporary shapefile.

Moreover, it is not possible to add the output layer to an exiting GPKG, SQLite... container without completely overwrite it.

Furthermore, it is not possible to properly select a layer ("Select file" in the algorithm window) from GPKG, SQLite, FileGDB containers in the case it is not already present in the map.

Back