4

A few days ago Cy T posted an interesting question about creating virtual layers using the Python console:

Creating new Virtual Layer programmatically in QGIS?

Is it also possible to create virtual layers through the processing toolbox?

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# ----- define interface -----
##Virtual Layers=group
##Point on surface (ST_PointOnSurface)=name
##Input_polygons=vector

from qgis.core import QgsVectorLayer, QgsMapLayerRegistry

inptlyr = processing.getObject(Input_polygons)

vlayer = QgsVectorLayer( "?query=SELECT rowid AS gid,ST_PointOnSurface(geometry)AS geom FROM inptlyr.name()", "vlayer", "virtual" )
QgsMapLayerRegistry.instance().addMapLayer(vlayer)

The log says Algorithm Point on surface (ST_PointOnSurface) finished, but nothing happens.

Edit: ?query= added

  • 1
    Maybe a ?query= missing? I mean, does it change something using ?query=SELECT ? – mgri Feb 11 '17 at 11:29
  • My fault, now QGIS crashes when running the script. – eclipsed_by_the_moon Feb 11 '17 at 11:49
5

I think the issue lies with inptlyr.name(). Since you inserted it into the string, this is exactly how it will be read (and I doubt you have a layer called "inptlyr.name()").

Personally, I find it easier to separate queries/formulae as it makes it easier to find mistakes. So the following example works for me:

##Virtual Layers=group
##Point on surface (ST_PointOnSurface)=name
##Input_polygons=vector

from qgis.core import QgsVectorLayer, QgsMapLayerRegistry

inptlyr = processing.getObject(Input_polygons)
query = """ SELECT * FROM '""" + inptlyr.name() + """' """

vlayer = QgsVectorLayer( "?query={}".format(query), "vlayer", "virtual" )
QgsMapLayerRegistry.instance().addMapLayer(vlayer)

Two things to notice:

  1. Single quotes are used for layer names (particularly useful when layer names contain spaces).

  2. inptlyr.name() is outside the string so that the name can be extracted correctly.

So when the above query is read by the script, it will look like:

SELECT * FROM 'polygon example'

This should be enough to create and load your virtual layer. You can test it by using your query.


EDIT:

Your code could look like the following:

##Virtual Layers=group
##Point on surface (ST_PointOnSurface)=name
##Input_polygons=vector

from qgis.core import QgsVectorLayer, QgsMapLayerRegistry

inptlyr = processing.getObject(Input_polygons)
query = """ SELECT rowid AS gid,ST_PointOnSurface(geometry)AS geom FROM '""" + inptlyr.name() + """' """

vlayer = QgsVectorLayer( "?query={}".format(query), "vlayer", "virtual" )
QgsMapLayerRegistry.instance().addMapLayer(vlayer)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.