Les routes genericqueries en GET

Les routes genericqueries permettent d'interroger n'importe quelle table d'une base de données accessible depuis vMap, sans qu'une route dédiée ait été déclarée pour cette table. Elles servent notamment à alimenter les listes de valeurs des formulaires ainsi que l'interface d'administration des sources de données.

Toutes ces routes sont en GET et exigent un jeton d'authentification valide (en-tête Authorization). Seule la route columns requiert un rôle particulier.

Méthode

Route

Objectif

Rôle requis

GET

/vitis/genericqueries/databases

liste les bases de données du serveur

—

GET

/vitis/genericqueries/{databaseName}/schemas

liste les schémas d'une base

—

GET

/vitis/genericqueries/schemas

liste les schémas d'une base, nom passé en paramètre

—

GET

/vitis/genericqueries/tables

liste les tables d'un schéma

—

GET

/vitis/genericqueries/columns

définition des colonnes d'une table, au format formulaire

vitis_admin

GET

/vitis/genericqueries

retourne le contenu d'une table

—


Choisir la base de données interrogée

Par défaut, les routes interrogent la base de données de l'application (propriété db_name). Pour interroger une base externe, il faut fournir l'ensemble des paramètres de connexion ; s'il en manque un seul, ils sont tous ignorés : la connexion est alors établie sur le serveur défini par les propriétés db_server et db_port, avec les identifiants de l'utilisateur porteur du jeton, sur la base indiquée par database.

Paramètre

Obligatoire

Description

database

non

nom de la base ; par défaut la base de l'application (db_name)

login

non

utilisateur de la base externe

password

non

mot de passe de la base externe

server

non

hôte du serveur de base de données

port

non

port d'écoute

sgbd

non

type de SGBD, par exemple pdo_pgsql ou pdo_oci

charset

non

jeu de caractères de la source, par exemple ISO-8859-1 ou WE8ISO8859P15

Note

Avec sgbd=pdo_oci, l'accès se fait par l'accesseur Oracle et le champ identifiant est déduit de la première colonne retournée.

Si charset vaut ISO-8859-1 ou WE8ISO8859P15, les chaînes retournées sont reconverties en UTF-8 avant d'être renvoyées.


GET /vitis/genericqueries/databases

Retourne la liste des bases de données du serveur PostgreSQL.

curl -X GET "https://[hostname]/vmap/v2/vitis/genericqueries/databases" \
     -H "Authorization: eyJhbGciOiJ..."
{
  "status": 1,
  "data": ["vmap", "metier", "..."]
}

Avertissement

Comme pour les schémas, aucun filtrage n'est appliqué : la route retourne le contenu de pg_database, ce qui inclut les bases système (postgres, template0, template1), sans tenir compte des droits de l'utilisateur sur ces bases. Le tri n'est pas garanti.

Les paramètres order_by et filter s'appliquent ici aussi, sur la colonne datname.


GET /vitis/genericqueries/{databaseName}/schemas

Retourne la liste des schémas de la base {databaseName}, passée dans l'URL.

curl -X GET "https://[hostname]/vmap/v2/vitis/genericqueries/vmap/schemas" \
     -H "Authorization: eyJhbGciOiJ..."
{
  "status": 1,
  "data": [
    "public",
    "s_vitis",
    "s_vmap_2",
    "s_cadastre",
    "data_demo_vmap",
    "..."
  ]
}

Avertissement

Aucun filtrage n'est appliqué : la route retourne tous les schémas de information_schema.schemata, y compris les schémas système de PostgreSQL (pg_catalog, pg_toast, information_schema) et le schéma technique de Vitis (s_vitis). Le tri n'est pas garanti non plus, la requête n'ayant pas d'ORDER BY par défaut.

Les paramètres order_by et filter permettent d'y remédier, par exemple pour ne garder que les schémas applicatifs :

order_by=schema_name
filter={"column":"schema_name","compare_operator":"LIKE","value":"s\_%"}

GET /vitis/genericqueries/schemas

Variante de la route précédente : le nom de la base est passé en paramètre plutôt que dans le chemin. Utile lorsque ce nom contient des caractères difficiles à échapper dans une URL.

Paramètre

Obligatoire

Description

database

oui

nom de la base de données

curl -X GET "https://[hostname]/vmap/v2/vitis/genericqueries/schemas?database=vmap" \
     -H "Authorization: eyJhbGciOiJ..."
{
  "status": 1,
  "data": [
    "public",
    "s_vitis",
    "s_vmap_2",
    "s_cadastre",
    "data_demo_vmap",
    "..."
  ]
}

Le paramètre database est obligatoire : s'il est absent, la réponse est MISSING_PARAMS. S'il est présent mais vide, la réponse est un succès accompagné d'une liste vide ({"data": [], "status": 1}) plutôt qu'une erreur.


GET /vitis/genericqueries/tables

Retourne la liste des tables (et vues) d'un schéma.

Paramètre

Obligatoire

Description

database

oui

nom de la base de données

schema

oui

nom du schéma

curl -X GET "https://[hostname]/vmap/v2/vitis/genericqueries/tables?database=vmap&schema=s_vmap_2" \
     -H "Authorization: eyJhbGciOiJ..."
{
  "status": 1,
  "data": ["map", "layer", "theme"]
}

Si database ou schema est absent, la réponse est {"status": 0, "errorMessage": "MISSING_PARAMS"}, avec un code HTTP 200.


GET /vitis/genericqueries/columns

Retourne la définition des colonnes d'une table, déjà transposée en champs de formulaire : cette route sert à construire un formulaire à partir d'une structure existante. Elle est réservée au rôle vitis_admin.

Paramètre

Obligatoire

Description

database

oui

nom de la base de données

schema

oui

schéma de la table

table

oui

nom de la table

curl -X GET "https://[hostname]/vmap/v2/vitis/genericqueries/columns" \
     -H "Authorization: eyJhbGciOiJ..." \
     -G \
     --data-urlencode "database=vmap" \
     --data-urlencode "schema=data_demo_vmap" \
     --data-urlencode "table=f_villes_l93"
{
  "status": 1,
  "data": [
    { "type": "text", "name": "code", "label": "code", "nb_cols": 12 },
    { "type": "text", "name": "nom", "label": "nom", "nb_cols": 12 },
    { "type": "integer", "name": "pop90", "label": "pop90", "nb_cols": 12 },
    { "type": "text", "name": "geom", "label": "geom", "nb_cols": 12 }
  ]
}

Le type SQL de chaque colonne est traduit en type de champ :

Type SQL

Type de champ

smallint, integer, bigint

integer

date, ainsi que tout type contenant time zone (timestamp without time zone, time with time zone…)

date

boolean

radio, avec les choix FORM_YES / FORM_NO

tout autre type

text

Note

Contrairement à la route de lecture, cette route liste toutes les colonnes de la table, y compris la colonne géométrique — typée text puisque geometry ne correspond à aucun type de champ dédié. Le libellé label reprend simplement le nom de la colonne : il est destiné à être réécrit.


GET /vitis/genericqueries

Retourne le contenu d'une table.

Paramètres de sélection

Paramètre

Obligatoire

Description

table

oui

nom de la table interrogée

schema

oui

schéma de la table

database

non

base de données ; par défaut celle de l'application

field_id

non

nom du champ identifiant ; il est automatiquement ajouté aux attributs

attributs

non

liste des colonnes à retourner, séparées par | ; toutes par défaut

distinct

non

true pour dédoublonner les résultats

order_by

non

colonne de tri ; ignorée si la colonne n'existe pas dans la table

sort_order

non

ASC (défaut) ou DESC

limit

non

nombre maximum de lignes retournées

offset

non

nombre de lignes ignorées en début de résultat

filter

non

filtre JSON, voir ci-dessous

Filtrage sur une valeur du formulaire

Les trois paramètres filter_attr, filter_value et values permettent de construire automatiquement un filtre IN : filter_attr est la colonne filtrée, values un objet contenant les valeurs du formulaire, et filter_value la clé de values dont le contenu sert de critère. Si cette clé est absente ou vide, la réponse est une erreur MISSING_PARAMS.

Ce mécanisme sert typiquement à alimenter une liste déroulante dépendante d'un autre champ du formulaire : values contient les valeurs courantes du formulaire, et la liste ne doit proposer que les enregistrements rattachés à l'une d'elles.

Soit une table metier.quartier possédant une colonne commune_id, et un formulaire dont le champ id_commune vaut 12. Pour ne récupérer que les quartiers de cette commune :

curl -X GET "https://[hostname]/vmap/v2/vitis/genericqueries" \
     -H "Authorization: eyJhbGciOiJ..." \
     -G \
     --data-urlencode "database=vmap" \
     --data-urlencode "schema=metier" \
     --data-urlencode "table=quartier" \
     --data-urlencode "attributs=quartier_id|nom" \
     --data-urlencode "filter_attr=commune_id" \
     --data-urlencode "filter_value=id_commune" \
     --data-urlencode "values[id_commune]=12"
  • filter_attr=commune_id : la colonne filtrée, dans la table interrogée ;

  • filter_value=id_commune : le nom de la clé à lire dans values, et non la valeur du critère ;

  • values[id_commune]=12 : la valeur effectivement utilisée.

L'appel ci-dessus équivaut donc à transmettre le filtre suivant :

{
  "relation": "AND",
  "operators": [
    { "column": "commune_id", "compare_operator": "IN", "value": "12" }
  ]
}
{
  "status": 1,
  "data": [
    { "quartier_id": 3, "nom": "Centre" },
    { "quartier_id": 7, "nom": "Gare" }
  ],
  "total_row_number": 2,
  "list_count": 2
}

Comme l'opérateur généré est un IN, plusieurs valeurs peuvent être transmises en passant un tableau : values[id_commune][]=12&values[id_commune][]=13 retourne les quartiers des deux communes.

Avertissement

Le filtre ainsi construit remplace le paramètre filter s'il est fourni dans le même appel : les deux ne se combinent pas. Pour croiser ce critère avec d'autres conditions, il faut écrire un unique filter contenant l'ensemble des opérateurs.

Si values ne contient pas la clé désignée par filter_value, ou si sa valeur est vide, la requête échoue avec MISSING_PARAMS et le message « La valeur de filter_value (...) n'est pas présente dans les valeurs » — la liste n'est pas retournée sans filtre.

Colonnes typées

Le paramètre columns_type permet de déclarer le type applicatif de certaines colonnes, sous la forme d'un objet {"nom_colonne": "type"}. Les types reconnus sont :

Type

Effet

image

la colonne est traitée comme un champ fichier image (nécessite file_path)

document

la colonne est traitée comme un champ fichier non image (nécessite file_path)

geom

la colonne est traitée comme une géométrie et retournée en EWKT

Soit une table metier.equipement dont la colonne photo stocke des noms de fichiers et la colonne geom une géométrie. Sans columns_type, photo est retournée telle qu'elle est stockée. En la déclarant comme image, l'API retourne à la place une URL de téléchargement du fichier :

curl -X GET "https://[hostname]/vmap/v2/vitis/genericqueries" \
     -H "Authorization: eyJhbGciOiJ..." \
     -G \
     --data-urlencode "database=vmap" \
     --data-urlencode "schema=metier" \
     --data-urlencode "table=equipement" \
     --data-urlencode "field_id=equipement_id" \
     --data-urlencode "attributs=equipement_id|nom|photo|geom" \
     --data-urlencode "columns_type[photo]=image" \
     --data-urlencode "columns_type[geom]=geom" \
     --data-urlencode "file_path=@prop(ws_data_dir)/metier/equipement/@id/@column/@value"
{
  "status": 1,
  "data": [
    {
      "equipement_id": 4,
      "nom": "Abribus",
      "photo": "https://[hostname]/vmap/v2/vitis/downloads?file=eyJhbGciOiJ...",
      "geom": "SRID=2154;POINT(652345.12 6862110.44)"
    }
  ],
  "total_row_number": 1,
  "list_count": 1
}

Le paramètre file_path est le gabarit de chemin du fichier sur le serveur. Il accepte les substitutions suivantes :

Substitution

Remplacée par

@prop(nom)

la valeur de la propriété nom du properties.json

@id

la valeur du champ identifiant de la ligne

@column

le nom de la colonne traitée

@value

la valeur stockée dans la colonne (le nom du fichier)

@attribute(colonne)

la valeur d'une autre colonne de la ligne

Note

field_id doit être renseigné pour les types image et document : sans lui, le chemin du fichier ne peut pas être calculé et la colonne est retournée à null (un avertissement est tracé dans le journal API_ERROR).

file_path est unique pour tout l'appel : si plusieurs colonnes sont déclarées image ou document, elles partagent le même gabarit. C'est le rôle de @column, qui permet de les ranger dans des répertoires distincts.

Les colonnes déclarées image ou document sont traitées comme des champs multi-fichiers : la valeur stockée est découpée sur le caractère |, et la réponse contient les URL correspondantes séparées par des virgules.

Note

Pour geom, la déclaration est le plus souvent inutile : les colonnes géométriques enregistrées dans public.geometry_columns sont détectées automatiquement et retournées en EWKT, avec leur SRID. columns_type sert dans les cas où cette détection n'aboutit pas, par exemple sur certaines vues.

Exemple de lecture d'une table

curl -X GET "https://[hostname]/vmap/v2/vitis/genericqueries" \
     -H "Authorization: eyJhbGciOiJ..." \
     -G \
     --data-urlencode "database=vmap" \
     --data-urlencode "schema=s_vmap_2" \
     --data-urlencode "table=map" \
     --data-urlencode "attributs=map_id|name" \
     --data-urlencode "order_by=name" \
     --data-urlencode "sort_order=ASC" \
     --data-urlencode "limit=50"

Structure de la réponse

{
  "status": 1,
  "data": [
    { "map_id": 1, "name": "Carte communale" },
    { "map_id": 2, "name": "Carte cadastrale" }
  ],
  "total_row_number": 2,
  "list_count": 2
}
  • total_row_number : nombre total de lignes correspondant au filtre, sans tenir compte de limit et offset ;

  • list_count : nombre de lignes effectivement retournées.

Erreurs courantes

Code HTTP

errorMessage

Cause

200

MISSING_PARAMS

table, schema ou database manquant

401

ERROR_MISSING_AUTHORIZATION_HEADER

en-tête Authorization absent

401

ERROR_SESSION_EXPIRED

jeton expiré

401

ERROR_POSTGRES_USER_BAD_CONNECTION

la connexion à la base n'a pas pu être établie


Le paramètre filter

Le paramètre filter attend un objet JSON (ou sa version sérialisée en chaîne) constitué d'une relation logique et d'une liste d'opérateurs :

{
  "relation": "AND",
  "operators": [
    { "column": "name", "compare_operator": "LIKE", "value": "%communale%" },
    { "column": "map_id", "compare_operator": ">=", "value": 10 }
  ]
}

Les filtres peuvent être imbriqués : un élément de operators peut lui-même être un objet {"relation": ..., "operators": [...]}. Un opérateur seul (objet comportant column et compare_operator) est également accepté : il est alors automatiquement encapsulé dans une relation AND.

Opérateurs de comparaison disponibles

Opérateur

Usage

=, !=, <>

égalité et différence

>, >=, <, <=

comparaisons

IN, NOT IN

appartenance à une liste ; value peut être un tableau

NULL / IS NULL

la colonne est nulle ; value n'est pas requis

NOT NULL / IS NOT NULL

la colonne est non nulle ; value n'est pas requis

LIKE

comparaison textuelle

PLAIN

recherche plein texte

INTERSECT

intersection géométrique (couches géographiques)

CONTAIN

inclusion géométrique

INSTANCEOF

test de type, en mode ORM uniquement

Avertissement

Un opérateur invalide, une colonne absente de la table ou une valeur manquante alors que l'opérateur en exige une entraîne l'abandon silencieux de la clause concernée : l'erreur est tracée dans le journal API_ERROR, mais la requête aboutit. Il convient donc de vérifier total_row_number lorsqu'un filtre semble sans effet.

Options des opérateurs

Certains opérateurs acceptent un objet compare_operator_options :

Option

Opérateurs concernés

Description

case_insensitive

LIKE

comparaison insensible à la casse (LOWER)

accent_insensitive

LIKE, PLAIN

comparaison insensible aux accents (unaccent)

source_proj

INTERSECT, CONTAIN

projection de la géométrie fournie

intersect_buffer

INTERSECT

tampon appliqué à la géométrie, dans l'unité de la projection

Note

Pour l'opérateur LIKE, dès lors que compare_operator_options est renseigné, les deux clés accent_insensitive et case_insensitive doivent être présentes.