[GIS] How to debug ‘Layer is not valid error’ from Python plugin

postgispyqgispythonqgisqgis-plugins

I'm trying to understand what goes wrong with a QGIS python plugin.
Basically I'm trying to render a series of POINT.

The query works fine, at least giving it by hand from inside PostGIS DB:

"SELECT  gid, CAST (gid as text)|| '_' || (ST_DumpPoints(the_geom)).path[2] as key,  (ST_DumpPoints(the_geom)).geom as points FROM ways"

I concat gid and path[2] because after splitting the_geom (MULTILINE) field into several POINT, gid are duplicated and I think they are no longer usable as key (with this trick key should be unique, but it seems not solve my problem).

I tried to create the layer this way:

def createPointLayer(self):
    uri = self.db.getURI()
    query = "SELECT  gid, CAST (gid as text)|| '_' || (ST_DumpPoints(the_geom)).path[2] as key,  (ST_DumpPoints(the_geom)).geom as points FROM ways"

    uri.setDataSource("", "(" + query + ")", "points","","key")
    layerName = "NodeLayer"
    aLayer = self.iface.addVectorLayer(uri.uri(), layerName, self.db.getProviderName())

I think the query works fine (QGIS takes a long time before display the error. I guess something goes wrong after the query has been executed).

When the plugins run QGIS output the following error:

Layer is not valid:

The layer dbname='pgrouting' user='user' password='user' key='gid'
table="(SELECT gid, CAST (gid as text)|| '_' ||
(ST_DumpPoints(the_geom)).path[2] as key,
(ST_DumpPoints(the_geom)).geom as points FROM ways)" (points) sql= is
not a valid layer and can not be added to the map

I already had to struggle against the Layer is not valid error, but I don't know how to debug it.
So I have 2 questions:

  1. Could anyone tell me what's my mistake in this specific case?
  2. How can I debug 'Layer not valid error'? How can I get more information on which is the problem?

EDIT:

QGIS log console display the following message:

No key field for query given

Best Answer

It seems your "key" field must have type integer and not text. I reproduced your problem with the following snippet:

uri = QgsDataSourceURI()
uri.setConnection("localhost", "5432", "mydb", "user", "pass")
query="SELECT  id, CAST (id as text)|| '_' || (ST_DumpPoints(geom)).path[2] as key, (ST_DumpPoints(geom)).geom as points FROM line"
uri.setDataSource("", "(" + query + ")", "points", "", "key")
vl = iface.addVectorLayer(uri.uri(), "QueryLayer", "postgres")

Only after I changed the "key" field type to "int", I could get the layer loaded into QGIS:

uri = QgsDataSourceURI()
uri.setConnection("localhost", "5432", "mydb", "user", "pass")
query="SELECT  id, CAST(CAST (id as text)|| (ST_DumpPoints(geom)).path[2] as int) as key, (ST_DumpPoints(geom)).geom as points FROM line"
uri.setDataSource("", "(" + query + ")", "points", "", "key")
vl = iface.addVectorLayer(uri.uri(), "QueryLayer", "postgres")

Note that I had to adjust your gid to id and your the_geom to geom, in order to work with my own data.