Documentation PostgreSQL 8.0.2 | ||||
---|---|---|---|---|
Précédent | Arrière rapide | Chapitre 42. Protocole d'interface et de moteur | Avance rapide | Suivant |
Cette section décrit le flux des messages et la sémantique de chaque type de message. (Les détails sur la représentation exacte de chaque message apparaît dans Section 42.4.) Il existe différents sous-protocoles suivant l'état de la connexion : lancement, requête, appel de fonction, COPY et fin. Il existe aussi des provisions spéciales pour les opérations asynchrones (incluant les réponses aux notifications et les annulations de commande), qui peuvent arriver à tout moment après la phase de lancement.
Pour commencer une session, un client ouvre une connexion au serveur et envoie un message de lancement. Ce message inclut les noms de l'utilisateur et de la base de données où le client souhaite se connecter ; il identifie aussi la version particulière du protocole à utiliser. (De façon optionnelle, le message de lancement peut inclure des configurations supplémentaires pour des paramètres en exécution.) Le serveur utiliser ensuite cette information et le contenu de ces fichiers de configuration (tels que pg_hba.conf) pour déterminer si la connexion est acceptable et quelle authentification supplémentaire est requis (si nécessaire).
Ensuite, le serveur envoie un message de demande d'authentification approprié, auquel le client doit répondre avec un message de réponse d'authentification approprié (tel qu'un mot de passe). En principe, le cycle demande/réponse d'authentification pourrait requérir plusieurs itérations mais aucune des méthodes d'authentification présentes utilisent plus d'un cycle demande/réponse. Avec d'autres méthodes, aucune réponse n'est nécessaire de la part du client et donc aucune demande d'authentification n'intervient.
Le cycle d'authentification se termine lorque le serveur rejete la tentative de connexion (ErrorResponse) ou l'accepte en envoyant AuthenticationOk.
Les messages possibles du serveur dans cette phase sont :
La tentative de connexion a été rejetée. Le serveur ferme immédiatement la connexion.
L'échange d'authentification s'est terminé avec succès.
Le client doit maintenant prendre part à un dialogue d'authentification Kerberos V4 (non décrit ici, car faisant parti de la spécification Kerberos) avec le serveur. Si cela résulte en un succès, le serveur répond avec un AuthenticationOk, sinon il répond avec un ErrorResponse.
Le client doit maintenant prendre part à un dialogue d'authentification Kerberos V5 (non décrit ici car faisant parti de la spécification Kerberos) avec le serveur. Si cela résulte en un succès, le serveur répond avec un AuthenticationOk, sinon il répond avec un ErrorResponse.
Le client doit maintenant envoyer un PasswordMessage contenant le mot de passe en clair. Si le mot de passe est le bon, le serveur répond avec un AuthenticationOk, sinon il répond avec un ErrorResponse.
Le client doit maintenant envoyer un PasswordMessage contenant le mot de passe crypté avec crypt(3) en utilisant le composant salt à deux caractères spécifié dans le message AuthenticationCryptPassword. Si le mot de passe est correct, le serveur répond avec un AuthenticationOk, sinon il répond avec un ErrorResponse.
Le client doit maintenant envoyer un PasswordMessage contenant le mot de passe crypté avec MD5 en utilisant le composant salt de quatre caractères donné dans le message AuthenticationMD5Password. Si le mot de passe est correct, le serveur répond avec un AuthenticationOk, sinon il répond avec un ErrorResponse.
Cette réponse est seulement possible pour les connexions locales en domaine Unix sur les plateformes qui supportent les messages crédentielles SCM. Le client doit envoyer un message crédentiel SCM, puis envoyer un seul octet de données. (Le contenu de cet octet n'est pas intéressant ; il est utilisé pour s'assurer que le serveur attend assez longtemps pour recevoir le message crédentiel.) Si la crédence est acceptable, le serveur répond avec un AuthenticationOk, sinon il répond avec un ErrorResponse.
Si le client ne supporte pas la méhode d'authentification demandée par le serveur, alors il devrait immédiatement fermer la connexion.
Après avoir reçu AuthenticationOk, le client doit attendre d'autres messages du serveur. Dans cette phase, un processu serveur est en cours de lancement et le client est simplement en attente. Il est encore possible que la tentative de lancement échoue (ErrorResponse) mais, dans le cas de base, le serveur enverra quelques messages ParameterStatus, BackendKeyData et enfin ReadyForQuery.
Pendant cette phase, le serveur tentera d'appliquer tous les paramètres supplémentaires en exécution qui sont donnés dans le message de lancement. En cas de succès, ces valeurs deviennent les valeurs par défaut de la session. Une erreur génère un ErrorResponse et quitte.
Les messages possibles du serveur dans cette phase sont :
Ce message fournit une donnée secrète de type clé que le client doit conserver s'il souhaite être capable d'envoyer des annulations de requêtes plus tard. Le client ne devrait pas répondre à ce message mais devrait continuer à attendre un message ReadyForQuery.
Ce message informe le client sur la configuration actuelle (initiale) des paramètres du serveur, comme client_encoding ou DateStyle. Le client peut ignorer ce message ou enregistrer la configuration pour ses besoins futurs ; voir Section 42.2.6 pour plus de détails. Le client ne devrait pas répondre à ce message mais continuer à attendre un message ReadyForQuery.
Le lancement est terminé. Le client pourrait envoyer dès maintenant des commandes.
Le lancement a échoué. La connexion est fermée après avoir envoyé ce message.
Un message d'avertissement a été envoyé. Le client devrait afficher ce message mais doit continuer à attendre un ReadyForQuery ou un ErrorResponse.
Le message ReadyForQuery est le même que celui que le serveur envoie à a chaque cycle de commande. Suivant les besoins de codage du client, il est raisonnable de considérer ReadyForQuery comme le début d'un cycle de commande et de considérer ReadyForQuery comme la fin de la phase de lancement et de chaque cycle de commande.
Un cycle de requête simple est initié par le client en envoyant un message Query au serveur. Le message inclut une commande SQL (ou des commandes) exprimée comme une chaîne texte. Ensuite, le serveur envoie un ou plusieurs messages en réponse suivant le contenu de la chaîne représentant la requête et enfin un message ReadyForQuery. ReadyForQuery informe le client qu'il peut envoyer une nouvelle commande. (Il n'est pas réellement nécessaire que le client attende ReadyForQuery avant de lancer une autre commande mais le client doit alors prendre la responsabilité de savoir ce qui arrive si la commande précédente échoue et que les commandes suivantes, déjà lancées, réussissent.)
Les messages de réponse du serveur sont :
Commande SQL terminée normalement.
Le serveur est prêt à copier des données du client vers une table voir Section 42.2.5.
Le serveur est prêt à copier des données d'une table vers le client ; voir Section 42.2.5.
Indique que les lignes sont prêtes à être renvoyées en réponse à une requête SELECT, FETCH, etc. Le contenu de ce message décrit le placement des colonnes dans les lignes. Il sera suivi d'un message DataRow pour chaque ligne renvoyée par le client.
Un des ensembles de lignes renvoyés par une requête SELECT, FETCH, etc.
Une chaîne de requête vide a été reconnue.
Une erreur est survenue.
Le traitement de la requête est terminé. Un message séparé est envoyé pour indiquer ceci parce que la chaîne de la requête pourrait contenir plusieurs commandes SQL. (CommandComplete marque la fin du traitement d'une commande SQL, pas de la chaîne complète.) ReadyForQuery sera toujours envoyé que le traitement se termine avec un succès ou avec une erreur.
Un message d'avertissement a été envoyé concernant la requête. Les avertissements sont en plus des autres réponses, c'est-à-dire que le serveur continuera à traiter la commande.
La réponse à une requête SELECT (ou à d'autres requêtes qui renvoient des ensembles de données tels que EXPLAIN ou SHOW) consiste normalement en un RowDescription, zéro ou plus de messages DataRow messages et enfin un CommandComplete. COPY vers ou du client demande un protocole spécial décrit dans Section 42.2.5. Toutes les autres types de requêtes produisent seulement un message CommandComplete.
Comme une chaîne de requête pourrait contenir plusieurs requêtes (séparées par des points virgules), il pourrait y avoir plusieurs séquences de réponses avant que le serveur finisse de traiter la chaîne de requête. ReadyForQuery est lancé quand la chaîne complète a été traitée et que le serveur est prêt à accepter une nouvelle chaîne de requêtes.
Si une chaîne de requêtes complètement vide est reçu (aucun contenu autre que des espaces blancs), la réponse est EmptyQueryResponse suivi par ReadyForQuery.
Dans le cas d'une erreur, ErrorResponse est lancé suivi par ReadyForQuery. Tous les traitements suivants de la chaîne de requêtes sont annulés par ErrorResponse (même si un grand nombre de requêtes restent à traiter). Notez que ceci pourrait survenir en plein milieu de la séquence des messages générés par une requête individuelle.
En mode simple requête, le format des valeurs récupérées est toujours du texte, sauf si la commande donnée est un FETCH à partir d'un curseur déclaré avec l'option BINARY. Dans ce cas, les valeurs récupérées sont au format binaire. Les codes de format donnés dans le message RowDescription indiquent le format utilisé.
La planification de requêtes pour des instructions préparées survient lorsque le message Parse est reçu. Si une requête sera exécuté de façon répété avec différents paramètres, il pourrait être bénéfique d'envoyer un seul message Parse contenant une requête avec paramètres, suivie de plusieurs messages Bind et Execute. Ceci évitera de planifier de nouveau la requête pour chaque exécution.
L'instruction préparée non nommée est planifiée lors du traitement de Parse si le message Parse ne définit aucun paramètre. Mais s'il existe des paramètres, la planification de la requête est repoussée jusqu'à ce que le premier message Bind de cette instruction est reçu. Le planificateur considèrera les valeurs réelles des paramètres fournies dans le message Bind lors de la planification de la requête.
Note : Les plans de requêtes générés à partir d'une requête avec paramètres pourraient être moins efficaces que les plans de requêtes générés à partir d'une requête équivalente dont les valeurs de paramètres réelles ont été placées. Le planificateur de requêtes ne peut pas prendre les décisions suivant les valeurs réelles des paramètres (par exemple, la sélectivité de l'index) lors de la planification d'une requête avec paramètres affectée à un objet instruction préparée nommée. La pénalité possible est évitée lors de l'utilisation d'une instruction non nommée car elle n'est pas planifiée jusqu'à ce que des valeurs réelles de paramètres soient disponibles.
Si un autre Bind référençant l'objet instruction préparée non nommée est reçu, la requête n'est pas de nouveau planifiée. Les valeurs de paramètres utilisées dans le premier message Bind pourrait produire un plan de requête qui est seulement efficace pour un sous-ensemble des valeurs de paramètres possibles. Pour forcer une nouvelle planification de la requête pour un ensemble nouveau de paramètres, envoyez un autre message Parse pour remplacer l'objet instruction préparée non nommée.
Un client doit être préparé à accepter des messages ErrorResponse et NoticeResponse à chaque fois qu'il s'attend à tout autre type de message. Voir aussi Section 42.2.6 concernant les messages que le client pourrait générer à cause d'événements extérieurs.
La pratique recommandée est de coder les clients dans un style de machine- état qui acceptera tout type de message à n'importe quel moment où cela aurait un sens, plutôt que de coder en dur les suppositions sur la séquence exacte des messages.
Le protocole de requête étendu casse le protocole de requête simple décrit ci-dessus en plusieurs étapes. Les résultats des étapes de préparation peuvent être utilisées de nouveau de nombreuses fois pour une efficacité améliorée. De plus, des fonctionnalités supplémentaires sont disponibles, telles que la possibilité de fournir des valeurs de données comme des paramètres séparés au lieu d'avoir à les insérer directement dans une chaîne de requêtes.
Dans le protocole étendu, le client envoie tout d'abord un message Parse qui contient une chaîne de requête, optionnellement quelques informations sur les types de données des emplacements des paramètres et le nom d'un objet d'une instruction préparée nommée (une chaîne vide sélectionne l'instruction préparée sans nom). La réponse est soit ParseComplete soit ErrorResponse. Les types de données des paramètres pourraient être spécifiés par l'OID ; si non donnés, l'analyseur tente d'inférer les types de données de la même façon comme il pourrait faire pour les constantes de chaîne littérale non typées.
Note : La chaîne contenue dans un message Parse ne peut pas inclure plus d'une instruction SQL ; sinon une erreur de syntaxe est rapportée. Cette restriction n'existe pas dans le protocole de requête simple mais il existe dans le protocole étendu parce permettre aux instructions préparées ou portails de contenir de multiples commandes compliquerait le procotole indumment.
Si créée avec succès, une instruction préparée nommée dure jusqu'à la fin de la session actuelle, sauf si détruit explicitement. Une instruction préparée non nommée dure uniquement jusqu'à la prochaine instruction Parse spécifiant que l'instruction non nommée est lancée comme destination. (Notez qu'un simple message Query détruit aussi l'instruction non nommée.) Les instructions préparées nommées doivent être explicitement fermées avant qu'ils puissent être redéfinis par un message Parse mais ceci n'est pas requis pour l'instruction non nommée. Les instructions préparées non nommées peuvent aussi être créées et accédées au niveau de commande SQL en utilisant PREPARE et EXECUTE.
Une fois qu'une instruction préparée existe, il peut être prêt à l'exécution en utilisant un message Bind. Le message Bind donne le nom de l'instruction préparée source (une chaîne vide dénote l'instruction préparée non nommée), le nom du portail destination (une chaîne vide dénote le portail non nommé) et les valeurs à utiliser pour tout emplacement de paramètres présent dans l'instruction préparée. L'ensemble de paramètres fournis doit correspondre à ceux nécessaire pour l'instruction préparée. Bind spécifie aussi le format à utiliser pour toutes les données renvoyées par la requête ; le format peut être spécifié complètement ou par colonne. La réponse est soit BindComplete soit ErrorResponse.
Note : Le choix entre la sortie texte et binaire est déterminé par les codes de format donnés dans Bind, quelque soit la commande SQL impliquée. L'attribut BINARY dans les déclarations du curseur n'est pas relevant à l'utilisation du protocole de requête étendue.
Si créé avec succès, un objet portail nommé dure jusqu'à la fin de la transaction actuelle sauf si elle est explicitement détruite. Un portail non nommé est détruite à la fin de la transaction ou aussi tôt que la prochaine instruction Bind spécifiant le portail non nommé de destination est lancée. (Notez qu'un simple message Query détruit aussi le portail non nommé.) Les portails nommés doivent être explicitement fermés avant qu'ils ne puissent être redéfinis par un message Bind mais ceci n'est pas requis pour le portail non nommé. Les portails nommés peuvent aussi être créés et accédés à ce niveau de commande SQL en utilisant DECLARE CURSOR et FETCH.
Une fois qu'un portail existe, il peut être exécuté en utilisant un message Execute. Ce message spécifie le nom du portail (une chaîne vide dénote le portail non nommé) et un nombre maximum de lignes de résultat (zéro signifiant << récupère toutes les lignes >>). Le nombre de lignes résultat a seulement un sens pour les portails contenant des commandes qui renvoient des ensembles de lignes ; dans d'autres cas, la commande est toujours exécutée jusqu'à la fin et le nombre de lignes est ignoré. Les réponses possibles d'Execute sont le même que celles décrites ci-dessus pour les requêtes lancées via le protocole de requête simple, sauf qu'Execute ne cause pas l'envoi de ReadyForQuery ou RowDescription.
Si Execute se termine avant la fin de l'exécution d'un portail (dû à l'arrivée d'un nombre de lignes de résultats différent de zéro), il enverra un message PortalSuspended ; l'apparence de ce message indique au client qu'un autre Execute devrait être lancé contre le même portail pour terminer l'opération. Le message CommandComplete indiquant la fin de la commande source SQL n'est pas envoyée jusqu'à la fin de l'exécution du portail. Donc, une phase Execute est toujours terminée par l'apparence d'exactement un de ces messages : CommandComplete, EmptyQueryResponse (si le portail était créé à partir d'une chaîne de requête vive), ErrorResponse ou PortalSuspended.
À la fin de chaque série de messages de requêtes étendues, le client devrait lancer un message Sync. Ce message sans paramètre fait que le serveur ferme la transaction actuelle s'il n'est pas à l'intérieur d'un bloc de transaction BEGIN/COMMIT (<< fermer >> signifiant valider s'il n'y a pas d'erreurs, ou annuler dans le cas contraire). Alors une réponse ReadyForQuery est lancée. Le but de Sync est de fournir un point de resynchronisation pour les récupérations d'erreurs. Quand une erreur est détectée lors du traitement d'un message de requête étendu, le serveur lance ErrorResponse, puis lit et annule les messages jusqu'à ce qu'un Sync soit atteint, puis lance ReadyForQuery et renvoie le traitement de messages normaux. (Mais notez qu'aucun échappement ne survient si une erreur est détectée tout en traitant Sync — ceci nous assure qu'il y a un et seulement un ReadyForQuery envoyé pour chaque Sync.)
Note : Sync ne cause pas un bloc de transactions ouvert avec un BEGIN à fermer. Il est possible de détecter cette situation car le message ReadyForQuery inclut une information de statut de transaction.
En plus de ces opérations fondamentales, requis, il y a plusieurs opérations optionnelles qui peut être utilisé avec le protocole de requête étendue.
Le message Describe (variante d'un portail) spécifie le nom d'un portail existant (ou une chaîne vide pour le portail non nommé). La réponse est un message RowDescription décrivant les lignes qui sera renvoyé en exécutant le portail ; ou un message NoData si le portail ne contient pas une requête qui renvoie des lignes ; ou ErrorResponse s'il n'existe pas un tel portail.
Le message Describe (variante de l'instruction) spécifie le nom d'une instruction préparée existante (ou une chaîne vide pour l'instruction préparée non nommée). La réponse est un message ParameterDescription décrivant les paramètres nécessaires à l'instruction, suivies par un message RowDescription décrivant les lignes qui seront renvoyées lorsque l'instrution est éventuellement exécutée (ou un message NoData si l'instruction ne renvoie pas de lignes). ErrorResponse est lancé s'il n'y a pas de telle instruction préparée. Notez que comme Bind n'a pas encore été lancé, les formats à utiliser pour les lignes renvoyées ne sont pas encore connues du serveur ; les champs du code de format dans le message RowDescription seront à zéro dans ce cas.
Astuce : Dans la plupart des scénarios, le client devrait lancer une variante ou une autre de Describe avant de lancer Execute pour vous assurer qu'il sait comment interpréter les résultats qu'il récupèrera.
Le message Close forme une instruction préparée ou un portail existant et libère les ressources. S'il ne s'agit pas d'une erreur pour lancer Close sur une instruction ou un portail inexistant. La réponse est normalement CloseComplete mais pourrait être ErrorResponse si une quelconque difficulté est rencontrée lors de la libération des ressources. Notez que fermer une instruction préparée ferme implicitement d'autres portails ouverts qui ont été construit à partir de cette instruction.
Le message Flush ne cause pas une sortie spécifique à être généré mais force le serveur à délivrer toutes données restantes dans les tampons de sortie. Un Flush doit être envoyé après qu'une commande de requête étendue sauf Sync, si le client souhaite examiner le résultat de cette commande avant de lancer plus de commandes. Sans Flush, les messages renvoyés par le serveur seront combinés dans le nombre minimum possible de paquets pour minimiser la surcharge réseau.
Note : Le simple message Query est approximativement équivalent aux séries Parse, Bind, au portail Describe, Execute, Close, Sync en utilisant les objets de l'instruction préparée non nommée et du portail, sans paramètres. Une différence est qu'il acceptera plusieurs instructions SQL dans la chaîne de requêtes, réalisant automatiquement la séquence bind/describe/execute pour chacune en succession. Une autre différence est qu'il ne renvoie pas les messages ParseComplete, BindComplete, CloseComplete ou NoData.
Le sous-protocole de l'appel de fonction permet au client de demander un appel direct de toute fonction qui existe dans le catalogue système pg_proc de la base de données. Le client doit avoir le droit d'exécution pour la fonction.
Note : Le sous-protocole d'appel de la fonction est une fonctionnalité qui est probablement mieux évitée dans le nouveau code. Des résultats similaires peuvent être accomplis en initialisant une instruction préparée qui lance SELECT function($1, ...). Le cycle de l'appel de fonction peut alors être remplacé avec Bind/Execute.
Un cycle d'appel de fonction est initié par le client envoyant un message FunctionCall au serveur. Ensuite, le serveur envoie un ou plusieurs messages de réponse suivant les résultats de l'appel de la fonction et finalement un message de réponse ReadyForQuery. ReadyForQuery informe le client qu'il pourrait envoyer en toute sécurité une nouvelle requête ou un nouvel appel de fonction.
Les messages de réponse possibles du serveur sont :
Une erreur est survenue.
L'appel de la fonction est terminé et a renvoyé le résultat donné dans le message. (Notez que le protocole d'appel de fonction peut seulement gérer un résultat scalaire simple, pas un type de ligne ou un ensemble de résultats.)
Le traitement de l'appel de fonction est terminé. ReadyForQuery sera toujours envoyé, que le traitement se termine avec succès ou avec une erreur.
Un message d'avertissement a été envoyé en relation avec l'appel de fonction. Les avertissements sont en supplément des autres réponses, c'est-à-dire que le seveur continuera à traiter la commande.
La commande COPY permet des transferts de données en lot vers ou du serveur. Les opérations Copy-in et copy-out basculent chacune la connexion dans un sous-protocole distinct, durant jusqu'à la fin de l'opération.
Le mode Copy-in (transfert de données vers le serveur) est initié quand le serveur exécute une instruction SQL COPY FROM STDIN. Le serveur envoie une message CopyInResponse au client. Le client devrait alors envoyer zéro ou plus de messages CopyData, formant un flux de données en entrée. (Les limites du message ne doivent pas avoir quoi que ce soit avec les limites de la ligne, bien que cela soit souvent un choix raisonnable.) Le client peut terminer le mode copy-in en envoyant soit un message CopyDone (permettant une fin avec succès) ou un message CopyFail (qui causera l'instruction SQL COPY pour échouer avec une erreur). Alors, le serveur retourne au mode de traitement de la commande qu'il était avant le début de COPY, qui sera le protocole de requête simple ou étendu. Ensuite, il enverra soit CommandComplete (en cas de succès) soit ErrorResponse (sinon).
Dans l'événement d'une erreur détectée par le moteur lors d'un mode copy-in (incluant la réception d'un message CopyFail), le serveur lancer un message ErrorResponse. Si la commande COPY a été lancée via un message de requête étendue, le serveur annulera maintenant des messages du client jusqu'à ce qu'un message Sync soit reçu, puis il enverra ReadyForQuery et retournera le traitement normal. Si la commande COPY a été lancée dans un message simple Query, le reste de ce message est annulé et ReadyForQuery est lancé. Dans ce cas, tous les messages conséquents à CopyData, CopyDone ou CopyFail lancés par l'interface seront simplement annulés.
Le serveur ignorera les messages Flush et Sync reçus lors d'un mode copy-in. La réception d'un autre type de message sans copie constitue une erreur qui annulera l'état copy-in décrite ci-dessus. (L'exception pour Flush et Sync est dans l'intérêt des bibliothèques clientes qui enverront toujours Flush ou Sync après un message Execute sans vérification si la commande à exécuter est un COPY FROM STDIN.)
Le mode Copy-out (transfert de données à partir du serveur) est initié lorsque le moteur exécute une instruction SQL COPY TO STDOUT. Le moteur envoie un message CopyOutResponse vers le client suivi par zéro ou plusieurs messages CopyData (toujours une par ligne), suivi par CopyDone. Ensuite, le serveur retourne au mode de traitement de la commande dans lequel il était avant le lancement de COPY et envoie CommandComplete. Le client ne peut pas annuler le tranfert (sauf en fermant la connexion ou en lançant une requête d'annulation), mais il peut annuler les messages CopyData et CopyDone non voulus.
Dans l'événement d'une erreur détectée du serveur lors du mode copy-out, le serveur lancera un message ErrorResponse et retournera dans le traitement normal. Le client pourrait traiter la réception d'un ErrorResponse (ou à la place tout type de message autre que CopyData ou CopyDone) en terminant le mode copy-out.
Les messages CopyInResponse et CopyOutResponse incluent les champs qui informent le client du nombre de colonnes par ligne et les codes de format en cas d'utilisation pour chaque colonne. (Comme l'implémentation en cours, toutes les colonnes dans une opération COPY donnée utilisera le même format mais la conception du message ne suppose pas ceci.)
Il existe plusieurs cas dans lequel le serveur enverra les messages qui ne sont pas spécifiquement demandés par le flux de commande du client. Les clients doivent être préparés à gérer ces messages à tout moment même s'ils ne sont pas la suite d'une requête. Au minimum, vous devriez vérifier ces cas avant de commencer à lire la réponse d'une requête.
Il est possible que les messages NoticeResponse soient générés en dehors de toute activité ; par exemple, si l'administrateur de la base de don nées commande un arrêt << rapide >> de la base de données, le serveur enverra un NoticeResponse indiquant ce fait avant de fermer la connexion. Ainsi, les clients devraient toujours être préparés avant de fermer la connxion et afficher les messages NoticeResponse, même si la connexion est sans activité.
Les messages ParameterStatus seront générés quand la valeur active modifie pour tous les paramètres que le serveur croit que le client devrait connaître. Plus habituellement, ceci survient en réponse à une commande SQL SET exécutée par le client et ce cas est effectivement synchrone — mais il est aussi possible pour que les changements de statut du paramètre survient à cause de l'administrateur a changé un fichier de configuration et envoie ensuite le signal SIGHUP au postmaster. De plus, si une commande SET est annulée, un message approprié ParameterStatus sera généré pour rapporter la valeur effective actuelle.
À présent, il y a un ensemble de paramètres codé en dur pour lesquels des ParameterStatus seront générés : il y a server_version, client_encoding, server_encoding, is_superuser, session_authorization et session_authorization, DateStyle, TimeZone et integer_datetimes. (server_encoding, TimeZone et integer_datetimes n'ont pas été reportés par les sorties avant la 8.0.) Notez que server_version, server_encoding et integer_datetimes sont des pseudo-paramètres qui ne peuvent pas changer après le lancement. Cet ensemble pourrait changer dans le futur ou même devenir configurable. De façon accordée, un client pourrait simplement ignorer un ParameterStatus pour les paramètres qu'il ne comprend pas ou ne fait pas attention.
Si un client lance une commande LISTEN, alors le serveur enverra un message NotificationResponse (à ne pas être confondu avec NoticeResponse !) quand une commande NOTIFY est exécutée pour le même nom de notification.
Note : Actuellement, NotificationResponse peut seulement être envoyé à l'extérieur d'une transaction et, du coup, il ne surviendra pas dans le milieu d'une série de réponse de commande bien qu'il pourrait survenir juste avant ReadyForQuery. Néanmoins, il est déconseillé de concevoir la logique du client qui assume cela. Une bonne pratique est d'être capable d'accepter NotificationResponse en tout point du protocole.
Pendant le traitement d'une requête, le client pourrait demander l'annulation de la requête. La requête d'annulation n'est pas envoyée directement sur la connexion ouverte vers le serveur pour des raisons d'efficacité de l'implémentation : nous ne voulons pas avoir le serveur vérifier constamment les nouvelles entrées à partir du client lors du traitement des requêtes. Les requêtes d'annulation devraient être relativement inhabituelles, donc nous les faisons simplement pour éviter une pénalité dans le cas normal.
Pour lancer une requête d'annulation, le client ouvre une nouvelle connexion vers le serveur et envoie un message CancelRequest plutôt que le message StartupMessage qui serait envoyé ordinairement vers une nouvelle connexion. Le serveur traitera cette requête, puis fermera la connexion. Pour les raisons de sécurité, aucune réponse directe n'est faite pour le message de requête d'annulation.
Un message CancelRequest sera ignoré sauf s'il contient le même donnée clé (PID et clé secrète) passé au client lors du lancement de la connexion. Si la requête correspond au PID et à la clé secrète pour un serveur exécuté en cours, le traitement de la requête en cours est annulé. (Dans l'implémentation existante, ceci se fait en envoyant un signal spécial au processus serveur qui traite la requête.)
Le signal d'annulation pourrait ou ne pourrait avoir aucun effet — par exemple, s'il arrive après que le serveur a terminé le traitement de la requête, alors il n'aura aucun effet. Si l'annulation est réelle, il résulte dans la commande bientôt terminée avec un message d'erreur.
The upshot of all this is that for reasons of both security and efficiency, the frontend has no direct way to tell whether a cancel request has succeeded. It must continue to wait for the backend to respond to the query. Issuing a cancel simply improves the odds that the current query will finish soon, and improves the odds that it will fail with an error message instead of succeeding.
Comme la requête d'annulation est envoyée via une nouvelle connexion au serveur et non pas au travers du lien de communication client/serveur, il est possible que la requête d'annulation soit lancée par un autre processus, pas seulement le client pour lequel la requête doit être annulée. Ceci pourrait avoir quelques bénéfices de flexibilité dans la construction d'applications multi-processus. Il introduit aussi un risque de sécurité dans le fait que des personnes non autorisées pourraient essayer d'annuler des requêtes. Le risque de sécurité est adressé en réclamant une clé secrète générée dynamiquement pour récupérer les requêtes d'annulation.
La procédure normale de fin est que le client envoie un message Terminate et ferme immédiatement la connexion. Sur la réception de ce message, le serveur ferme la connexion et se termine.
Dans les cas rares (tels qu'un arrêt de la base de données commandé par l'administrateur), le serveur pourrait se déconnecter sans requête du client de le faire. Dans de tels cas, le serveur tentera d'envoyer un message d'erreur ou d'avertissement en donnant la raison pour la déconnexion avant de fermer la connexion.
D'autres scénarios de fin surviennent à partir de différents cas d'échecs, tels qu'un << core dump >> à un moment ou à un autre, perte du lien de connexion, perte de synchronisation des limites du message, etc. Si soit le client soit le serveur s'aperçoit d'une fermeture de la connexion, il devrait nettoyer et terminer. Le client a l'option de lancer un nouveau serveur en recontactant le serveur s'il ne veut pas se terminer lui-même. Fermer la connexion est aussi conseillable si un type de message non reconnu est reçu car ceci indique probablement la perte de synchronisation de limite des messages.
Pour une fin soit normale soit anormale, toute transaction ouverte est annulée, et non pas validée. Vous devriez néanmoins noté que si un client se déconnecte alors qu'une requête autre qu'un SELECT est en cours de traitement, le serveur terminera probablement la requête avant de noter la déconnexion. Si la requête est en dehors d'un bloc de transaction (séquence BEGIN ... COMMIT), alors les résultats pourraient être validés avant que la connexion soit reconnue.
Si PostgreSQL a été construit avec le support de SSL, les communications client/serveur peuvent être cryptées en utilisant SSL. Ceci fournit la sécurité de la communication dans les environnements où les attaquants pourraient être capable de capturer le trafic de la session. Pour plus d'informations sur le cryptage des sessions PostgreSQL avec SSL, voir Section 16.7.
Pour initier une connexion cryptée via SSL, le client envoie initialement un message SSLRequest plutôt qu'un StartupMessage. Ensuite, le serveur répond avec un seul octet contenant S ou N indiquant s'il souhaite ou non traiter SSL. Le client pourrait fermer la connexion à ce point s'il n'est pas satisfait de la réponse. Pour continuer avec S, réalisez un cycle de lancement SSL (non décrit ici car faisant partie de la spécification SSL) avec le serveur. En cas de succès, continuez avec l'envoi du StartupMessage habituel. Dans ce cas, StartupMessage et toutes les données suivantes seront cryptés avec SSL. Pour continuer après N, envoyez le StartupMessage habituel et continuez sans cryptage.
Le client devrait aussi être préparé à gérer une réponse ErrorMessage à un SSLRequest provenant du serveur. Ceci pourrait seulement survenir si le serveur ne dispose pas du support de SSL dans PostgreSQL. Dans ce cas, la connexion doit être fermée, mais le client pourrait choisir d'ouvrir une nouvelle connexion et procéder sans demander SSL.
Un SSLRequest initial pourrait être utilisé dans une connexion en cours d'ouverture pour envoyer un message CancelRequest.
Alors que le protocole lui-même ne fournit pas au serveur de façon de forcer le cryptage SSL, l'administrateur pourrait configurer le serveur pour rejeter les sessions non cryptées comme autre façon de vérifier l'authentification.
Précédent | Sommaire | Suivant |
Protocole d'interface et de moteur | Niveau supérieur | Types de données de message |