Articles marqués ‘edigeo’
[GDAL-OGR] Mode ajout dans une base de données PostGreSQL
Il y a quelques temps je devais importer des données au format EDIGEO dans une base PostGreSQL/PostGIS existante. J’avais plusieurs fichiers THF à importer par conséquent je devais créer la table puis importer les fichiers les nus après les autres. Après lecture attentive de la documentation puis poser quelques questions sur la liste gdal, voici la méthode ainsi que les petites astuces qui font la différence.
Visualisation du problème
Puisque la table n’existe pas au premier fichier THF, il faut que la commande ogr2ogr s’en occupe puis, dans un deuxième temps, il faut que cette même commande ajoute les données. La doc est assez clair là dessus : il faut lancer deux commandes l’une après l’autre (en fait seules quelques options sont différentes) :
ogr2ogr -gt 65536 -f "PostgreSQL" "PG:dbname=test host='localhost'" -lco "GEOMETRY_NAME=the_geom" -lco "SCHEMA=test" -lco "OVERWRITE=YES" -nln EDIGEO_parcelle E0001.THF PARCELLE_id
Cette commande s’exécute sans problème. Les options utilisées ici sont les suivantes :
- -gt 65536 : permet de grouper les géométries par groupe de 65 536 géométries avant de les commiter. Cela évite de commiter les géométries les unes après les autres. La valeur utilisée est celle préconiser par la documentation.
- -lco « SCHEMA=test » : importer les données dans un schéma particulier.
- -lco « GEOMETRY_NAME=the_geom » : totalement inutile mais j’aime bien avoir une cohérence dans mes noms de colonnes géométriques.
- -lco « OVERWRITE=YES » : obligatoire quand on fait plusieurs essaie ou quand la table existe déjà pour cause d’import déjà réalisé. Cette option indique que la table sera écrasée (détruite puis recrée).
- -nln EDIGEO_parcelle : donner un nom différent à la table que l’on va créer. Notez le mélange de majuscules et de minuscule, nous en reparlerons plus tard.
La deuxième commande que j’ai testé pour ajouter les données à une table existante esty celle-ci :
ogr2ogr -append -update -gt 65536 -f "PostgreSQL" "PG:dbname=test host='localhost'" -lco "GEOMETRY_NAME=the_geom" -lco "SCHEMA=test" -nln EDIGEO_parcelle E0002.THF PARCELLE_id
Et là, ca marche beaucoup moins bien car je reçois ce message :
ERROR 1: Layer test.edigeo_parcelle already exists, CreateLayer failed. Use the layer creation option OVERWRITE=YES to replace it. ERROR 1: Terminating translation prematurely after failed translation of layer PARCELLE_id (use -skipfailures to skip errors)
Et les logs de PostgreSQL montrent que cela ne provient pas de la base de données :
Postgresql log file shows: 2013-03-06 15:35:44 CET LOG: could not receive data from client: Connection reset by peer 2013-03-06 15:35:44 CET LOG: unexpected EOF on client connection
Compréhension du problème et solution
En regardant les logs d’un peu plus près, voici ce que l’on y trouve :
- le nom de la table créée est test.edigeo_parcelle, ce qui est incorrecte en regard de la commande que j’ai lancé (le nom de la table aurait dû être EDIGEO_parcelle.
- une commande est réalisée lors du mode ajout et celle-ci ne cherche pas la table dans le schéma test mais dans le schéma public.
Ces deux problèmes peuvent être réglés de plusieurs manières différentes.
La solution « fainéant »
Résumons la par « Ah ben ca marche pas avec des majuscules et dans un schéma autre que le schéma public, tant pis ». La solution ici est de mettre le nom de la table en minuscule (bonne pratique) et celle-ci dans le schéma public (pas bien !).
La solution dite de « contournement »
Elle s’approche de la première car elle n’utilise pas les options nécessaires (et ajoutées pour) ce cas de figure et elle ne sert qu’au deuxième problème (celui du schéma) :
ogr2ogr -append -update -gt 65536 -f "PostgreSQL" "PG:dbname=test host='localhost'" -nln test.edigeo_parcelle E0002.THF PARCELLE_id
Notez ces modifications :
- -lco « SCHEMA=test » et -lco « GEOMETRY_NAME=the_geom » ont été supprimés car inutile. Les options -lco ne sont pas utilisées en mode append ou update (ben oui le c de lco est pour « création », logique !).
- le nom de la table dans l’option -nln a été modifié en test.edigeo_parcele : tout en minuscule et ajout du schéma
La solution qui utilise les bonnes options
Comprenons bien les problèmes. Un premier problème vient du fait que le nom de la table que nous souhaitons créer contient des majuscules qui sont transformés en minuscule. Le deuxième problème vient du fait que nous utilisons une option de création pour définir le schéma dans lequel insérer des données alors que nous somme en mode append/update.
Nettoyage des noms de couches/table, colonne
Le pilote PostgreSQL dans GDAL/OGR contient un système de nettoyage des valeurs données lors de la création d’une couche. Cette option se nomme « LAUNDER » et est définie dans la page du pilote : http://gdal.gloobe.org/ogr/formats/pg.html (en français) :
Elle peut être définie à *YES* pour forcer les nouveaux champs créés sur cette couche à avoir les noms de champs « nettoyés » dans une forme compatible avec PostgreSQL. Cela convertie la valeur en minuscule ainsi que certains caractères spéciaux comme « – » et « # » en « _ ». Si la valeur *NO* est utilisée les noms exacts seront préservés. La valeur par défaut est *YES*. Si activé le nom de la table (couche) sera également nettoyé.
Si l’on souhaite garder nos majuscules il faut définir cette option à « NO ».
Définition du schéma en mode append/update
Lorsque nous somme en mode append ou update, nous ne somme pas en mode de création. C’est peu de le dire, c’est évident, mais au final on n’en saisit pas toujours les conséquences : les options de création ne nous serons d’aucune utilité ! Heureusement il y a une possibilité : le paramètre « active_schema » dans la chaîne de connexion. Notre commande devient alors :
ogr2ogr -append -update -gt 65536 -f "PostgreSQL" "PG:dbname=test host='localhost' active_schema=test" -nln edigeo_parcelle E0002.THF PARCELLE_id
Merci à Even Rouault pour son aide sur la liste.