Chapitre 42. Protocole d'interface et de moteur

Table des matières
42.1. Aperçu
42.1.1. Aperçu des messages
42.1.2. Aperçu des requêtes étendues
42.1.3. Formats et codes de format
42.2. Flux de messages
42.2.1. Lancement
42.2.2. Requête simple
42.2.3. Requête étendue
42.2.4. Appel de fonction
42.2.5. Opérations COPY
42.2.6. Opérations asynchrones
42.2.7. Annulation de requêtes en cours
42.2.8. Fin
42.2.9. Cryptage de la session SSL
42.3. Types de données de message
42.4. Formats de message
42.5. Champs des messages d'erreur et d'avertissement
42.6. Résumé des modifications depuis le protocole 2.0

PostgreSQL utilie un protocole basé sur les messages pour la communication entre les interfaces et le moteur (clients et serveurs). Le protocole passe sur TCP/IP mais aussi via des sockets de domaine Unix. Le numéro de port 5432 a été enregistré par l'IANA comme numéro de port TCP personnalisé pour les serveurs supportant ce protocole mais en pratique tout numéro de port non privilégié pourrait être utilisé.

Ce document décrit la version 3.0 de ce protocole, implémentée dans PostgreSQL 7.4 et ultérieure. Pour des descriptions des versions de protocoles précédentes, voir les précédentes versions de la documentation de PostgreSQL. Un serveur seul peur supporter plusieurs versions du protocole. Le message initial de demande de lancement indique au serveur la version du protocole que le client souhaite utiliser, ensuite le serveur suit ce protocole s'il en est capable.

Les fonctionnalités de haut niveau construites sur ce protocole (par exemple, la façon dont libpq passe certaines variables d'environnement lorsque la connexion est établie) sont couvertes ailleurs.

Pour répondre à de multiple clients de façon efficace, le serveur lance un nouveau serveur (<< backend >>) pour chaque client. Dans l'implémentation actuelle, un nouveau processus fils est créé immédiatement après qu'une connexion entrante est détectée. Néanmoins, ceci est transparent dans le protocole. Pour le but du protocole, les termes << backend >> et << serveur >> sont interchangeables ; comme << frontend >>, << interface >> et << client >>.

42.1. Aperçu

Le protocole a différentes phases pour le lancement et les opérations normales. Dans la phase de lancement, le client ouvre une connexion au serveur et s'authentifie lui-même à la satisfaction du serveur. (Ceci pourrait impliquer un message simple ou plusieurs messages suivant la méthode d'authentification utilisée.) Si tout se passe bien, le serveur envoie alors une information de statut au client et entre finalement en mode d'opérations normales. Sauf en ce qui concernen le message de demande de lancement, cette partie du protocole est conduite par le serveur.

Lors des opérations normales, le client envoie des requêtes et autres commandes au serveur et celui-ci renvoie les résultats des requêtes ainsi que d'autres réponses. Il existe quelque cas (comme NOTIFY) où le serveur enverra des messages non sollicités mais pour la plupart cette partie de la session est conduite par les requêtes du client.

La fin de la session est normalement au choix du client mais peut être forcé par le moteur dans certains cas. Dans tous les cas, lorsque le serveur termine la connexion, il annulera toute transaction ouverte (non terminée) avant de quitter.

Pendant les opérations normales, les commandes SQL peuvent être exécutées via deux sous-protocoles. Dans le protocole des << requêtes simples >>, le client envoie juste une chaîne, la requête, qui est analysée et exécutée immédiatement par le serveur. Dans le protocole des << requêtes étendues >>, le traitement des requêtes est séparé dans de nombreuses étapes : l'analyse, le lien avec les valeurs de paramètres et l'exécution. Ceci offre une flexibilité et bénéfices au nioveau performance au prix d'une complexité supplémentaire.

Les opérations normales ont des sous-protocoles supplémentaires pour certaines opérations comme COPY.

42.1.1. Aperçu des messages

Toute la communication se base sur un flux de messages. Le premier octet d'un message identifie le type de message et les quatre prochains octets spécifient la longueur du reste du message (cette longueur s'inclut elle-même, mais pas l'octet du type de message). Le contenu restant du message est déterminé par le type de message. Pour des raisons historiques, le tout premier message envoyé par le client (le message de lancement) n'a pas d'octet initial du type de message.

Pour éviter de perdre la synchronisation avec le flux de messages, le serveur et le client lisent typiquement un message entier dans un tampon (en utilisant le nombre d'octets) avant de tenter de traiter son contenu. Ceci permet une récupération simple si une erreur est détectée lors du traitement du contenu. Dans les situations extrêmes (telles que ne pas avoir assez de mémoire pour placer le message dans le tampon), le récepteur pourrait utiliser le nombre d'octets pour déterminer l'entrée à passer avant de continuer la lecture des messages.

Sinon, les serveurs et les clients doivent faire attention à ne pas envoyer un message incomplet. Ceci se fait habituellement en plaçant le message entier dans un tampon avant de commencer à l'envoyer. Su un échec de communications survient pendant l'envoi ou la réception d'un message, la seule réponse sensible est d'abandonner la connexion car il y a peu d'espoir de récupérer la ssynchronisation des messages.

42.1.2. Aperçu des requêtes étendues

Dans le protocole des requêtes étendues, l'exécution de commandes SQL est divisée en plusieurs étapes. L'état retenu entre les étapes est représenté par deux types d'objets : les instructions préparées et les portails. Une instruction préparée représente le résultat de l'analyse, de l'analyse de la sémantique et de la planification d'une chaîne de requête. Une instruction préparée n'est pas nécessairement prête à être exécutée parce qu'elle pourrait ne pas avoir certaines valeurs pour les paramètres. Un portail représente une instruction prête à être exécutée ou déjà-partiellement-exécutée, dont toutes les valeurs de paramètres manquantes sont connues. (Pour les instructions SELECT, un portail est équivalent un curseur ouvert mais nous choisissons d'utiliser un terme différent car les curseurs ne gèrent pas les instructions autres que SELECT.)

Le cycle d'exécution complet consiste en une étape d'analyse, qui crée une instruction préparée à partir d'une chaîne de requêtes ; une étape de liens, qui crée un portail à partir d'une instruction préparée et des valeurs pour les paramètres nécessaires ; et une étape d'exécution qui exécute une requête du portail. Dans le cas d'une requête qui renvoie des lignes (SELECT, SHOW, etc), l'étape d'exécution doit savoir s'il doit récupérer qu'un nombre limité de lignes, pour que des étapes d'exécution multipless soient nécessaires pour terminer l'opération.

Le serveur peut garder trace de plusieurs instructions préparées et de portails (mais notez qu'elles existent seulement à l'intérieur d'une session, et ne sont jamais partagées entre les sessions). Les instructions préparées et les portails existants sont référencés par les noms affectés lors de leur création. En plus, une instruction préparée et un portail << sans nom >> existent. Bien qu'ils se comportent largement comme les objets nommés, les opérations sur eux sont optimisées dans le cas une requête est exécutée une seule fois puis est annulée, alors que les opérations sur les objets nommés sont optimisés pour être utilisés de nombreuses fois.

42.1.3. Formats et codes de format

La donnée d'un type de donnée particulier pourrait être transmis dans plusieurs formats différents. À partir de PostgreSQL 7.4, les seuls formats supportés sont le << texte >> et le << binaire >> mais le protocole fait provision des extensions futures. Le format désiré pour toute valeur est spécifié par un code de format. Les clients pourraient spécifier un code de format pour chaque valeur de paramètre transmise et pour chaque colonne du résultat d'une requête. Le texte a le code de format zéro, le binaire a le code un et tous les autres codes de format sont réservés pour des définitions futures.

Le représentation texte des valeurs est toute chaîne produite et acceptée par les fonctions de conversion en entrée/sortie pour le type de données particulier. Dans la représentation transmise, il n'y a pas de caractère nul à la fin ; le client doit en ajouter un pour les valeurs reçues si il souhaite les traiter comme des chaînes C. (Le format texte n'autorise pas les valeurs nulles intégrées.)

Les représentations binaires pour les entiers utilisent l'ordre d'octet réseau (octet le plus significatif en premier). Pour les autres types de données, consultez la documentation ou le code source pour en apprendre sur la représentation binaire. Gardez en tête que les représentations binaires pour les types de données complexes pourraient changer entre les versions du serveur ; le format texte est habituellement le choix le plus portable.