Blog

Blog

PostGIS

PostGIS est le cartouche de données géographiques de postgreSQL. C'est le pendant d'Oracle spatial (que je connais nettement moins).

Création d'une base de données géographiques

Pour créer une base de données géographique, c'est relativement simple : Il suffit de créer une base de données normale et d'y jouer les scripts lwpostgis.sql et spatial_ref_sys.sql (généralement dans le répertoire share d'installation de votre version de postgreSQL).

Ces scripts créent les fonctions, objets, procédures et tables nécessaires à la manipulation de données géographiques.

Créer une table comportant des données géographiques

C'est tout simple : on commence par créer une table normale (CREATE TABLE...) et on ajoute ensuite la (ou les) colonne(s) géographique(s) à la main grâce à :

AddGeometryColumn(
  schema_name,
  table_name,
  column_name,
  srid,
  type,
  dimension
)

Spatial_ref_sys et geometry_columns

PostGIS utilise deux tables pour fonctionner : spatial_ref_sys et geometry_columns.
La table spatial_ref_sys comporte les colonnes suivantes :
DEMO_GEO=# \d spatial_ref_sys
         Table "public.spatial_ref_sys"
  Column   |          Type           | Modifiers
-----------+-------------------------+-----------
 srid      | integer                 | not null
 auth_name | character varying(256)  |
 auth_srid | integer                 |
 srtext    | character varying(2048) |
 proj4text | character varying(2048) |
Indexes:
    "spatial_ref_sys_pkey" PRIMARY KEY, btree (srid)

Cette table comporte les données nécessaires à l'utilisation de plus de 3000 systèmes de projections différents. A priori, vous n'aurez pas besoin de mettre les mains dedans. Elle est générée et peuplée par le script spatial_ref_sys.sql.

La table geometry_columns va beaucoup plus nous intéresser lorsqu'il s'agira de jouer au rebouteux pour données géographiques malades...
Voici la description de cette table :
DEMO_GEO=# \d geometry_columns
Table "public.geometry_columns"
     Column       |          Type          | Modifiers
-------------------+------------------------+-----------
f_table_catalog   | character varying(256) | not null
f_table_schema    | character varying(256) | not null
f_table_name      | character varying(256) | not null
f_geometry_column | character varying(256) | not null
coord_dimension   | integer                | not null
srid              | integer                | not null
type              | character varying(30)  | not null
Indexes:
"geometry_columns_pk" PRIMARY KEY, btree (f_table_catalog, f_table_schema, f_table_name, f_geometry_column)

Cette table comporte toutes les données concernant les colonnes de types géométriques qui se trouvent dans votre base. Exportez seulement vos schémas ou tables comportant vos données géographiques en omettant les données de cette table et vous aurez de jolies surprises lors de votre import dans une autre BDD.

Voici la description des colonnes de cette table :
  • f_catalog, f_schema, f_table et f_geometry_column permettent d'identifier avec précision la table (f_catalog est toujours vide)
  • coord_dimension permet de savoir s'il s'agit de données en 2D, 3D ou 4D
  • srid est le srid du système de projection utilisé (cf spatial_ref_sys)
  • type permet de savoir le type de données géométriques stockées (point, lignes, polygones...)

Ajouter manuellement des données dans geometry_columns

Vous avez fait des exports/imports de données dans une nouvelle base mais il vous manque les données de geometry_columns. Malheureusement votre sauvegarde est corrompue et vous ne savez pas comment récupérer les données de geometry_columns. (Ne riez pas, ça arrive!)

Pour chaque table avec des données géographiques, vous trouverez facilement les données à mettre dans f_schema, f_table et f_geometry_column.

Pour ce qui est des données à mettre dans coord_dimension et type, il va falloir être plus sioux.
Votre alliée se nomme pg_constraint. pg_constraint est une table du catalogue qui regroupe toutes les données liées aux contraintes.

DEMO_GEO=# \d pg_constraint
    Table "pg_catalog.pg_constraint"
    Column     |    Type    | Modifiers
---------------+------------+-----------
 conname       | name       | not null
 connamespace  | oid        | not null
 contype       | "char"     | not null
 condeferrable | boolean    | not null
 condeferred   | boolean    | not null
 conrelid      | oid        | not null
 contypid      | oid        | not null
 confrelid     | oid        | not null
 confupdtype   | "char"     | not null
 confdeltype   | "char"     | not null
 confmatchtype | "char"     | not null
 conkey        | smallint[] |
 confkey       | smallint[] |
 conpfeqop     | oid[]      |
 conppeqop     | oid[]      |
 conffeqop     | oid[]      |
 conbin        | text       |
 consrc        | text       |
Indexes:
    "pg_constraint_oid_index" UNIQUE, btree (oid)
    "pg_constraint_conname_nsp_index" btree (conname, connamespace)
    "pg_constraint_conrelid_index" btree (conrelid)
    "pg_constraint_contypid_index" btree (contypid)

Pour chaque colonne de type géographique, vous aurez 3 contraintes, une pour le srid, une pour la dimension et une pour le type de géométrie.
Il ne vous reste donc plus qu'à lancer la requête magique suivante :
SELECT c.consrc
FROM pg_constraint c
  INNER JOIN pg_class r ON c.conrelid = r.oid
  INNER JOIN pg_attribute a ON a.attnum = ANY (c.conkey)
WHERE r.relname = 'table_avec_colonne_geo'
  AND a.attname = 'colonne_geo'
  AND c.conname LIKE 'enforce%'

Vous recevrez un résultat de ce type :
        consrc               |         conname
----------------------------------------------------------+
 (srid(the_geom) = 4326)     | enforce_srid_the_geom
 (ndims(the_geom) = 2)       | enforce_dims_the_geom
 ((geometrytype(the_geom) =  | enforce_geotype_the_geom
 'POLYGON'::text) OR         |
 (the_geom IS NULL))         | 
Vous trouvez donc le SRID (4326), la dimension (2) et le type (POLYGON).