PostgreSQLLa base de données la plus sophistiquée au monde.

44.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 le code d'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. [9] %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 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 sujet à une traduction. 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 44.3, « Guide de style des messages d'erreurs ».



[9] C'est-à-dire que 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.