Programmation coté client
Introduction
L’utilisation de PostgreSQL par des applications nécessite de comprendre et maîtriser la façon dont l’application se connecte à PostgreSQL, et la façon dont les requêtes sont envoyées et les résultats sont récupérés.
Pilote de connexion
Le pilote de connexion est le composant logiciel que l’application cliente utilise pour se connecter à PostgreSQL. Il s’agit d’une bibliothèque de fonctions permettant d’ouvrir et de fermer des connexions, et aussi d’envoyer des requêtes SQL, de récupérer les résultats, de modifier des variables de sessions et de transactions, c’est-à-dire tout ce qui concerne la relation entre l’application cliente et le serveur PostgreSQL.
PostgreSQL fournit une bibliothèque implémentant ces fonctionnalités, la libpq. Fournie avec PostgreSQL, elle est écrite en langage C et s’intègre donc très naturellement dans une application cliente écrite en langage C. Pour d’autres langages s’interfaçant facilement avec le langage C, comme le PHP, il existe des encapsulations pour utiliser facilement les fonctionnalités de la bibliothèque.
D’autres langages peuvent bénéficier d’une implémentation native des fonctionnalités, sans utiliser la bibliothèque libpq, comme par exemple les langages Java ou GO. Lorsqu’un langage ne dispose pas de pilote, il est parfois possible d’utiliser des interfaces génériques comme ODBC.
Le tableau suivant résume les principaux pilotes de connexion, en fonctions des langages, et indique s’ils...
Requêtes préparées
Une fois la session ouverte dans la base de données, il est bien sûr possible d’envoyer une requête SQL et de récupérer le résultat, en prenant soin de paramétrer les données en entrée, pour contrer les tentatives d’injection SQL. Et dans une session, il est aussi possible de préparer une requête avant de l’exécuter.
Cette préparation consiste à déterminer un plan d’exécution, puis à réutiliser ce plan pour plusieurs exécutions successives, dans la même session. Le temps passé à déterminer ce plan d’exécution est alors économisé, et le plan est alors le même pour une requête donnée pendant tout le temps de la session.
Cette fonctionnalité est particulièrement intéressante lorsqu’une même requête est exécutée un grand nombre de fois dans la même session, et ce d’autant plus que le calcul du plan d’exécution est coûteux. Néanmoins, il faut noter qu’une requête préparée n’est visible et utilisable que dans la session dans laquelle elle est préparée.
La première étape est de préparer le plan d’exécution de la requête dans l’instance PostgreSQL...
Curseurs
Un curseur est utilisé par une application pour récupérer les résultats des requêtes : de cette façon, il est possible de récupérer une quantité contrôlée d’enregistrements, ce qui est particulièrement utile lorsque la requête SQL est susceptible de retourner un grand nombre d’enregistrements. Un curseur déclaré est utilisable pendant toute la durée de la transaction, mais pas au-delà.
La commande DECLARE permet d’enregistrer un curseur, correspondant à une requête, dans la session courante. Le synopsis de la commande est le suivant :
DECLARE nom [ BINARY ]
[ [ NO ] SCROLL ]
CURSOR
[ { WITH | WITHOUT } HOLD ]
FOR requete
L’option BINARY permet de retourner les données au format binaire de PostgreSQL. Les données doivent alors être décodées par l’application cliente.
L’option SCROLL autorise la récupération des résultats dans un ordre différent de l’ordre normal de la requête. L’option NO interdit ce comportement. Par compatibilité, PostgreSQL adopte le comportement de l’option SCROLL par défaut lorsque la requête SQL est assez simple pour le permettre sans surcoût.
L’option HOLD permet de conserver...
Récupération de résultats paginés sans curseur
Un curseur est souvent utilisé lorsque l’application n’a besoin que d’une partie des résultats pour les afficher dans une page, puis en fonction des interactions avec les utilisateurs, récupérer les résultats suivants, et ainsi de suite.
Mais selon l’application et l’architecture logicielle, il n’est pas toujours possible de maintenir la session et la transaction ouvertes. Souvent dans un contexte d’application web, on exécute à nouveau la requête pour trouver les bons enregistrements. Les clauses LIMIT et OFFSET sont utilisables pour ne récupérer que les enregistrements utiles, à condition qu’ils soient triés, ici sur le champ cli_id :
SELECT cli_id, cmd_cli_email_livraison
FROM commandes.commande_client
WHERE cmd_cli_time BETWEEN '2016-01-01'
AND '2016-02-01'
ORDER BY cli_id
LIMIT 10
OFFSET 10 ;
┌────────┬─────────────────────────┐
│ cli_id │ cmd_cli_email_livraison │
├────────┼─────────────────────────┤ ...