Les messages d'erreurs, d'alertes et de traces produites dans
le code du serveur doivent être créés avec
ereport
ou son ancien cousin elog
.
L'utilisation de cette fonction est suffisamment complexe pour nécessiter
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 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
produits par appel de fonctions auxiliaires, comme
errmsg
, dans l'appel à
ereport
.
Un appel typique à ereport
peut ressembler à :
ereport(ERROR, (errcode(ERRCODE_DIVISION_BY_ZERO), errmsg("division by zero")));
Le niveau de sévérité de l'erreur est ainsi positionné à ERROR
(une erreur banale). L'appel à errcode
précise
l'erreur SQLSTATE en utilisant une macro définie dans
src/include/utils/errcodes.h
. L'appel à
errmsg
fournit le message texte primaire.
L'ensemble supplémentaire de parenthèses entourant les appels aux
fonctions auxiliaires est ennuyeux mais syntaxiquement
nécessaire.
Exemple plus complexe :
ereport(ERROR, (errcode(ERRCODE_AMBIGUOUS_FUNCTION), errmsg("function %s is not unique", func_signature_string(funcname, nargs, NIL, actual_arg_types)), errhint("Unable to choose a best candidate function. " "You might need to add explicit typecasts.")));
Cela 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.
Si le niveau de sévérité est ERROR
ou plus,
ereport
annule l'exécution de la fonction définie par
l'utilisateur et ne rend pas la main à l'appelant. Si le niveau de
sévérité est moins qu'ERROR
, ereport
rend la main normalement.
Les routines auxiliaires disponibles pour ereport
sont :
errcode(sqlerrcode)
précise le code SQLSTATE de
l'identifiant erreur pour la condition. Si cette routine
n'est pas appelée, l'identifiant l'erreur est, par défaut,
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, il faut se demander si elles
sont appropriées avant d'omettre l'appel à
errcode()
.
errmsg(const char *msg, ...)
indique le message
texte primaire de l'erreur et les possibles valeurs d'exécutions
à y insérer. Les insertions sont précisées par les codes
de formatage dans le style sprintf
. En plus des
codes de formatage standard 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
.
[14]
%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 ni traduite ni incluse 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.
errmsg_plural(const char *fmt_singular, const char *fmt_plural,
unsigned long n, ...)
est identique à errmsg
mais avec le support pour plusieurs formes de pluriel du message.
fmt_singular
est le format singulier de
l'anglais, fmt_plural
est le format pluriel en
anglais, n
est la valeur entière qui détermine
la forme utilisée. Les arguments restants sont formatés suivant le chaîne
de format sélectionnée. Pour plus d'informations, voir
Section 55.2.2.
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
.
errdetail_internal(const char *msg, ...)
est
identique à errdetail
, sauf que le message ne
sera ni traduit ni inclut dans le dictionnaire des messages à
traduire. Elle doit être utilisée pour les messages de niveau détail
pour lequel un effort de traduction est inutile, par exemple parce
qu'ils sont trop techniques pour que cela soit utile à la majorité
des utilisateurs.
errdetail_plural(const char *fmt_singular, const char *fmt_plural,
unsigned long n, ...)
est identique à errdetail
mais avec le support de plusieurs formes de pluriel pour le message. Pour
plus d'information, voir Section 55.2.2.
errdetail_log(const char *msg, ...)
est identique à
errdetail
sauf que cette chaîne ne va que dans les
traces du serveur. Elle n'est jamais envoyée au client. Si
errdetail
(ou un de ses équivalents ci-dessus)
et errdetail_log
sont
utilisées ensemble, alors une chaîne est envoyés au client et l'autre dans
les traces du serveur. C'est utile pour les détails d'erreur qui concernent
la sécurité ou qui sont trop techniques pour être inclus dans le rapport
envoyé au client.
errdetail_log_plural(const char *fmt_singular, const char
*fmt_plural, unsigned long n, ...)
est identique à
errdetail_log
, mais avec le support de plusieurs
formes de pluriel pour le message.
Pour plus d'informations, voir Section 55.2.2.
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.
errtable(Relation rel)
spécifie une relation dont le
nom et le schéma doivent être inclus comme champs auxiliaires du rapport
d'erreur.
errtablecol(Relation rel, int attnum)
indique une
colonne dont le nom, le nom de la table et le nom du schéma doivent être
inclus comme champs auxiliaires du rapport d'erreur.
errtableconstraint(Relation rel, const char *conname)
spécifie une contrainte de table dont le nom, le nom de la table et le
nom du schéma doivent être inclus comme champs du rapport d'erreur. Les
index doivent être considérés comme des contraintes dans ce but, qu'ils
soient ou non associés à une entrée dans
pg_constraint
. Faites attention à fournir la
relation principale sous-jacente et non pas l'index lui-même, via
rel
.
errdatatype(Oid datatypeOid)
spécifie un type de
données dont le nom et le nom du schéma doivent être inclus comme
champs auxiliaires dans le rapport d'erreur.
errdomainconstraint(Oid datatypeOid, const char *conname)
spécifie une contrainte de domaine dont le nom, le nom du domaine et le
nom du schéma doivent être inclus comme champs auxiliaires du rapport
d'erreur.
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.
errhidestmt(bool hide_stmt)
peut être appelé pour
indiquer la suppression de la portion STATEMENT:
d'un
message dans le journal applicatif de postmaster. Habituellement, c'est
approprié si le texte du message contient déjà l'instruction en cours.
errhidecontext(bool hide_ctx)
peut être appelé pour
spécifier la suppression de la portion CONTEXT:
d'un
message dans les traces de postmaster. Ceci devrait seulement être utilisé
pour les messages verbeux de débogage où l'inclusion répétée de contexte
ferait grossir les journaux trop fortement.
Au moins une des fonctions errtable
,
errtablecol
, errtableconstraint
,
errdatatype
ou errdomainconstraint
doivent être utilisées dans un appel à ereport
. Ces
fonctions existent pour permettre aux applications d'extraire le nom de
l'objet de la base associé à l'erreur sans avoir à examiner le texte du
messahe d'erreur potentiellement traduit. Ces fonctions doivent être
utilisées dans les rapports d'erreur pour lesquels il est probable que
les applications voudraient une gestion automatique des erreurs. À partir
de PostgreSQL 9.3, une couverture complète existe
pour les erreurs de la classe SQLSTATE 23 (violation des contraintes
d'intégrité), mais il est probable que cette couverture soit étendue dans
les prochaines versions.
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", ...)));
Le code d'erreur SQLSTATE est toujours celui par défaut,
la chaîne de caractères du message n'est pas sujette à traduction.
Par conséquent,
elog
ne devrait être utilisé que pour les erreurs
internes et l'enregistrement de trace de débogage de bas niveau.
N'importe quel message susceptible d'intéresser
les utilisateurs ordinaires devrait passer par
ereport
. Néanmoins, il y a suffisamment de contrôles
des erreurs internes qui « ne peuvent pas arriver » dans le
système, pour que elog
soit toujours largement
utilisée ; elle est préférée pour ces messages du fait de sa simplicité
d'écriture.
Des conseils sur l'écriture de bons messages d'erreurs peuvent être trouvés dans la Section 54.3.
[14]
C'est-à-dire la valeur qui était courante quand l'appel à
ereport
a été atteinte ; les changements
d'errno
dans les routines auxiliaires de rapports
ne l'affecteront pas. Cela ne sera pas vrai si vous devez
écrire explicitement strerror(errno)
dans la liste
de paramètres de errmsg
; en conséquence ne faites
pas comme ça.