Projet

Général

Profil

Actions

Anomalie #369

ouvert

[AsgardMenu 0.1.7] Erreur sur le rafraîchissement

Ajouté par Leslie Lemaire il y a plus de 3 ans. Mis à jour il y a plus de 3 ans.

Statut:
Nouveau
Priorité:
Normal
Assigné à:
-
Version cible:
-
Début:
12/10/2020
Echéance:
% réalisé:

0%

Temps estimé:
# ref:

Description

Bonsoir Alain,

Je viens d'avoir l'erreur python suivante sur ma première tentative de rafraîchissement du menu :

2020-10-12T17:56:26     WARNING    Traceback (most recent call last):
              File "C:/Users/leslie.lemaire/AppData/Roaming/QGIS/QGIS3\profiles\default/python/plugins\AsgardMenu\asgard_menu.py", line 120, in reload_menu
              self.dlg.restore_session()
              File "C:/Users/leslie.lemaire/AppData/Roaming/QGIS/QGIS3\profiles\default/python/plugins\AsgardMenu\asgard_menu_dialog.py", line 733, in restore_session
              self.show_dock(bool(dock))
              File "C:/Users/leslie.lemaire/AppData/Roaming/QGIS/QGIS3\profiles\default/python/plugins\AsgardMenu\asgard_menu_dialog.py", line 159, in show_dock
              self.update_model(self.dock_model)
              File "C:/Users/leslie.lemaire/AppData/Roaming/QGIS/QGIS3\profiles\default/python/plugins\AsgardMenu\asgard_menu_dialog.py", line 464, in update_model
              for name, profile, model_index, comment, layername, end_datasource_uri, relkind, typegeom, permission, connection, attkey, attfirst in self.sortby_modelindex(rows):
              File "C:/Users/leslie.lemaire/AppData/Roaming/QGIS/QGIS3\profiles\default/python/plugins\AsgardMenu\asgard_menu_dialog.py", line 352, in sortby_modelindex
              key=lambda line: '/'.join(
              File "C:/Users/leslie.lemaire/AppData/Roaming/QGIS/QGIS3\profiles\default/python/plugins\AsgardMenu\asgard_menu_dialog.py", line 353, in 
              ['{:04}'.format(elem[0]) for elem in json.loads(line[2])]
              File "C:\PROGRA~1\QGIS 3.10\apps\Python37\lib\json\__init__.py", line 348, in loads
              return _default_decoder.decode(s)
              File "C:\PROGRA~1\QGIS 3.10\apps\Python37\lib\json\decoder.py", line 337, in decode
              obj, end = self.raw_decode(s, idx=_w(s, 0).end())
              File "C:\PROGRA~1\QGIS 3.10\apps\Python37\lib\json\decoder.py", line 353, in raw_decode
              obj, end = self.scan_once(s, idx)
             json.decoder.JSONDecodeError: Expecting ',' delimiter: line 1 column 56 (char 55)

Mis à jour par Leslie Lemaire il y a plus de 3 ans

Pas sûr que ce soit lié au rafraîchissement, en fait. J'ai maintenant le même problème quand je désactive et réactive manuellement l'une des bases. Possible que ce soit une affaire de caractères interdits utilisés dans les noms d'objets - c'est une base sur laquelle j'ai fait pas de tests avec ça. Je creuse de mon côté.

Mis à jour par Leslie Lemaire il y a plus de 3 ans

Ok, visiblement les guillemets doubles dans model_index ne passent pas (normal, c'est le délimitateur de JSON pour les chaînes de caractères). En l'occurrence c'était sur un nom d'objet, ce qui représente sans doute un cas improbable, mais le problème est le même avec les guillemets sur niv1, niv2... J'ai fait quelques essais, visiblement il faut remplacer " par \" pour que ça fonctionne.

Mis à jour par alain ferraton il y a plus de 3 ans

Pour être sûr de comprendre... tu veux dire que le pb est quand on utilise des " dans les champs niv1, niv2 ou un nom d'objet.
Où faut-il remplacer " par \"... directement dans les champs ou il y a une modification à faire dans le code ?

Mis à jour par Leslie Lemaire il y a plus de 3 ans

Non, bien sûr, il ne s'agit pas de mettre des \" dans le contenu des champs - les utilisateurs ne comprendraient pas - mais de gérer correctement les " lors de la construction de model_index.

Concrètement, ça veut dire remplacer mon bricolage par des casts propres. Je pense que ça marche avec to_json.

        '[[0, ' || to_json(upper(current_database())::text)::text || '], [' ||
            ind1b || ', ' || to_json(replace(niv1b, '&', 'et')::text)::text || '], [' ||
            ind2b || ', ' || to_json(replace(niv2b, '&', 'et')::text)::text || ']' || 
            CASE WHEN niv2 IS NOT NULL
                THEN ', [' || (row_number() OVER(PARTITION BY niv1b, niv2 ORDER BY relname) -1)::text
                    || ', ' || to_json(relname::text)::text || ']'
                ELSE '' END || ']'
        AS model_index

Mis à jour par alain ferraton il y a plus de 3 ans

Pour les noms d'objets, je n'arrive pas à me dépatouiller... car si on obtient bien un menu avec des " dans les noms (ce qui est quand même vicieux !)
la chaîne de chargement
datasource_uri= vector:postgres:COMM"UNEX:dbname='geaobase_asgard' host=localhost port=5432 user='consult.defaut' password='consult.defaut' sslmode=disable srid=2154 type=MULTIPOLYGON table="c_agri_agroalimentaire"."COMM\"UNEX" (geom) sql=::

Avec table=<...>."COMM\"UNEX" est interprété comme
dbname='geaobase_asgard' host=localhost port=5432 user='consult.defaut' sslmode=disable srid=2154 type=MultiPolygon checkPrimaryKeyUnicity='1' table="c_agri_agroalimentaire"."COMM" sql=
par QGIS. Le nom de la table est donc tronqué au 1er \"
tu as une idée de comment il faudrait passer la chaîne de connexion avec des " dans le nom d'une table ?

Mis à jour par Leslie Lemaire il y a plus de 3 ans

Je dirais qu'il faut les doubler :

datasource_uri= vector:postgres:COMM"UNEX:dbname='geaobase_asgard' host=localhost port=5432 user='consult.defaut' password='consult.defaut' sslmode=disable srid=2154 type=MULTIPOLYGON table="c_agri_agroalimentaire"."COMM""UNEX" (geom) sql=::

Mis à jour par alain ferraton il y a plus de 3 ans

J'ai oublié de préciser que j'avais tenté cette solution en utilisant quote_ident

<...> table="'::text) || nom_schema::text) || '".'::text) || quote_ident(relname::text)::text) <...>

Pour l'instant çà fait carrément planter QGIS... j'arrête pour ce soir !

Mis à jour par Leslie Lemaire il y a plus de 3 ans

Même si quote_ident avait résolu le problème des noms non standard, ça n'aurait pas marché avec ceux qui ont une forme identifiant-compatible, qui perdent alors leurs guillemets. Or les guillemets sur le nom de la table et le nom du schéma ne semblent pas optionnelles ici. Raison pour laquelle je n'ai pas utilisé quote_ident sur nom_schema et relname et concaténé les guillemets à la main à la place. Mais c'est très moche et pas du tout robuste, comme on peut le voir en l'occurrence.

Quoiqu'il en soit, doubler les guillemets n'est pas la solution. Il faut vraiment des \", si j'en crois les chaînes de connexion que j'obtiens en faisant les choses plus proprement.

En fait, je me suis dit qu'il serait bien plus robuste de construire les chaînes de connexion avec les méthodes prévues pour ça de QgsDataSourceUri.

Si j'ai créé la table :

CREATE TABLE a_test."table à ""problème"" !" (id serial PRIMARY KEY, geom geometry(POINT, 2154)) ;

Elle peut être chargée (sans erreur !) avec :

data_uri = QgsDataSourceUri()
data_uri.setConnection("localhost", "5432", "geobase_snum", "", "")
data_uri.setDataSource("a_test", 'table à "problème" !', "geom")
layer = QgsVectorLayer(data_uri.uri(), "Table sans problème", "postgres")
QgsProject.instance().addMapLayer(layer)

URI qui apparaît dans les propriétés de la couche :

dbname='geobase_snum' host=localhost port=5432 key='id' checkPrimaryKeyUnicity='1' table="a_test"."table à \"problème\" !" (geom) sql=

Et dans le QGS :

dbname='geobase_snum' host=localhost port=5432 key='id' checkPrimaryKeyUnicity='1' table=&quot;a_test&quot;.&quot;table à \&quot;problème\&quot; !&quot; (geom) sql=

Si la table n'avait pas eu de clé primaire, on aurait pu désigner le champ d'identifiant unique :

data_uri.setDataSource("a_test", 'table à "problème" !', "geom", "", "id")

Pour une table non géométrique, je n'ai pas l'impression que ça fonctionne avec QgsDataSource (la couche est invalide quand on met "" pour le nom du champ de géométrie), mais on peut définir séparément la table, le schéma et, si nécessaire, le champ d'identifiant unique.

Exemple avec le chargement de la vue gestion_schema_etr :

data_uri = QgsDataSourceUri()
data_uri.setConnection("localhost", "5432", "geobase_snum", "", "")
data_uri.setSchema("z_asgard")
data_uri.setTable("gestion_schema_etr")
data_uri.setKeyColumn("nom_schema")
layer = QgsVectorLayer(data_uri.uri(), "Vue technique sur gestion schéma", "postgres")
QgsProject.instance().addMapLayer(layer)

Actions

Formats disponibles : Atom PDF