45.2. Reporter les erreurs dans le serveur
Les messages d'erreurs, d'alertes et de traces générés à l'intérieur
du code du serveur doivent être créés en utilisant ereport ou son ancien cousin elog. L'utilisation de cette fonction est assez
complexe pour que cela requiert quelques explications.
Il y a deux éléments requis pour chaque message : un niveau de
sévérité (allant de DEBUG à PANIC) et un message texte primaire. De plus, il y a
des éléments optionnels, le plus commun d'entre eux est le code
d'identifiant de l'erreur qui suit les conventions SQLSTATE des
spécifications SQL. ereport en elle-même
n'est qu'une fonction shell qui existe principalement pour des
convenances syntaxiques faisant ressembler la génération de messages
à l'appel d'une fonction dans un code source C. Le seul paramètre
directement accepté par ereport est le
niveau de sévérité. Le message texte primaire et les autres éléments
de messages optionnels sont générés en appelant des fonctions
auxiliaires, comme errmsg, à l'intérieur de
l'appel à ereport.
Un appel typique à ereport peut ressembler
à ceci :
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
Ceci met le niveau de sévérité de l'erreur à ERROR (une erreur banale). L'appel à errcode spécifie l'erreur SQLSTATE en utilisant une
macro définie dans src/include/utils/errcodes.h. L'appel à errmsg fournit le message texte primaire. Notez
l'ensemble supplémentaire de parenthèses entourant les appels aux
fonctions auxiliaires (cela est ennuyeux mais syntaxiquement
nécessaire).
Voici un exemple plus complexe :
ereport(ERROR,
(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
errmsg("function %s is not unique",
func_signature_string(funcname, nargs,
actual_arg_types)),
errhint("Unable to choose a best candidate function. "
"You may need to add explicit typecasts.")));
Ceci illustre l'utilisation des codes de formatage pour intégrer des
valeurs d'exécution dans un message texte. Un message
« conseil », optionnel, est
également fourni.
Les routines auxiliaires disponibles pour ereport sont :
-
errcode(sqlerrcode) spécifie le code
SQLSTATE de l'identifiant de l'erreur pour la condition. Si
cette routine n'est pas appelée, par défaut, l'identifiant de
l'erreur sera ERRCODE_INTERNAL_ERROR
quand le niveau de sévérité de l'erreur est ERROR ou plus haut, ERRCODE_WARNING quand le niveau d'erreur est
WARNING et ERRCODE_SUCCESSFUL_COMPLETION pour NOTICE et inférieur. Bien que ces valeurs par
défaut soient souvent commodes, demandez-vous toujours si elles
sont appropriées avant d'omettre l'appel à errcode().
-
errmsg(const char *msg, ...) spécifie
le message texte primaire de l'erreur et les possibles valeurs
d'exécutions à insérer dedans. Les insertions sont spécifiées
par les codes de formatage dans le style sprintf. En plus des codes de formatage
standards acceptés par sprintf, le
code %m peut être utilisé pour insérer
le message d'erreur retourné par strerror pour la valeur courante de errno. []
%m ne nécessite aucune entrée
correspondante dans la liste de paramètres pour errmsg. Notez que la chaîne de caractères du
message sera passée à travers gettext
pour une possible adaptation linguistique avant que les codes
de formatage ne soient exécutés.
-
errmsg_internal(const char *msg, ...)
fait la même chose que errmsg à
l'exception que la chaîne de caractères du message ne sera pas
inclue dans le dictionnaire de messages d'internationalisation.
Cela devrait être utilisé pour les cas qui « ne peuvent pas arriver » et pour lesquels
il n'est probablement pas intéressant de déployer un effort de
traduction.
-
errdetail(const char *msg, ...)
fournit un message « détail » optionnel ; cela est utilisé quand
il y a des informations supplémentaires qu'il semble inadéquat
de mettre dans le message primaire. La chaîne de caractères du
message est traitée de la même manière que celle de errmsg.
-
errhint(const char *msg, ...) fournit
un message « conseil »
optionnel ; cela est utilisé pour offrir des suggestions sur la
façon de régler un problème, par opposition aux détails
effectifs au sujet de ce qui a mal tourné. La chaîne de
caractères du message est traitée de la même manière que celle
de errmsg.
-
errcontext(const char *msg, ...)
n'est normalement pas appelée directement depuis un site de
message de ereport mais plutôt elle
est utilisée dans les fonctions de rappels error_context_stack pour fournir des
informations à propos du contexte dans lequel une erreur s'est
produite, comme les endroits courants dans la fonction PL. La
chaîne de caractères du message est traitée de la même manière
que celle de errmsg. À l'inverse des
autres fonctions auxiliaires, celle-ci peut être appelée plus
d'une fois dans un appel de ereport ;
les chaînes successives ainsi fournies sont concaténées et
séparées pas des caractères d'interlignes (NL).
-
errposition(int cursorpos) spécifie
l'endroit textuel d'une erreur dans la chaîne de caractères de
la requête. Actuellement, c'est seulement utile pour les
erreurs détectées dans les phases d'analyses lexicales et
syntaxiques du traitement de la requête.
-
errcode_for_file_access() est une
fonction commode qui sélectionne l'identifiant d'erreur
SQLSTATE approprié pour une défaillance dans l'appel système
relatif à l'accès d'un fichier. Elle utilise le errno sauvegardé pour déterminer quel code
d'erreur générer. Habituellement cela devrait être utilisé en
combinaison avec %m dans le texte du
message d'erreur primaire.
-
errcode_for_socket_access() est une
fonction commode qui sélectionne l'identifiant d'erreur
SQLSTATE approprié pour une défaillance dans l'appel système
relatif à une socket.
Il y a une plus ancienne fonction nommée elog, qui est toujours largement utilisée. Un appel à
elog
elog(niveau, "chaine format", ...);
est strictement équivalent à
ereport(level, (errmsg_internal("chaine format", ...)));
Notez que le code d'erreur SQLSTATE est toujours par défaut et que la
chaîne de caractères du message n'est pas inclue dans le dictionnaire
de messages d'internationalisation. Par conséquent, elog devrait être utilisé seulement pour les erreurs
internes et l'enregistrement de trace de débogage de bas niveau.
N'importe quel message qui est susceptible d'être intéressant pour
les utilisateurs ordinaires devrait passer par ereport. Néanmoins, il y a assez de contrôles
d'erreurs internes qui « ne peuvent pas
arriver » dans le système, que elog est toujours largement utilisé ; pour ces
messages, cela est préféré à cause de sa simplicité d'écriture.
Des conseils sur l'écriture de bons messages d'erreurs peuvent être
trouvés dans la Section 45.3,
« Guide de style des messages d'erreurs ».