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

30.9. Gestion des erreurs

Cette section décrit la gestion des conditions exceptionnelles et des avertissements dans un programme SQL embarqué. Il existe plusieurs fonctions non exclusives pour cela.

30.9.1. Configurer des rappels

Une méthode simple de récupération des erreurs et des avertissements consiste à configurer une action spécifique à exécuter à chaque fois qu'une condition particulière survient. En général :

EXEC SQL WHENEVER condition action;

condition peut prendre une des valeurs suivantes :

SQLERROR

L'action spécifiée est appelée lorsqu'une erreur survient pendant l'exécution d'une instruction SQL.

SQLWARNING

L'action spécifiée est appelée lorsqu'un avertissement survient pendant l'exécution d'une instruction SQL.

NOT FOUND

L'action spécifiée est appelée lorsqu'une instruction ne récupère ou n'affecte aucune ligne (cette condition n'est pas une erreur mais il peut être intéressant de la gérer de façon particulière).

action peut avoir une des valeurs suivantes :

CONTINUE

Signifie effectivement que la condition est ignorée. Ceci est la valeur par défaut.

GOTO label, GO TO label

Saute au label spécifié (en utilisant une instruction C goto).

SQLPRINT

Affiche un message sur la sortie standard. Ceci est utile pour des programmes simples ou lors d'un prototypage. Les détails du message ne peuvent pas être configurés.

STOP

Appel de exit(1), ce qui terminera le programme.

BREAK

Exécute l'instruction C break. Ceci devrait être utilisé uniquement dans des boucles ou dans des instructions switch.

CALL nom (args), DO nom (args)

Appelle les fonctions C spécifiées avec les arguments spécifiés.

Le standard SQL ne définit que les actions CONTINUE et GOTO (et GO TO).

Voici un exemple utilisable dans un programme simple. Il affiche un message lorsqu'un avertissement survient et termine le programme quand une erreur se produit.

EXEC SQL WHENEVER SQLWARNING SQLPRINT;
EXEC SQL WHENEVER SQLERROR STOP;

L'instruction EXEC SQL WHENEVER est une directive du préprocesseur SQL, pas une instruction C. Les actions sur les erreurs et avertissements qu'elle définit s'appliquent à toutes les instructions SQL embarquées qui apparaissent avant l'endroit où le gestionnaire est défini, à moins qu'une action différente n'ait été définie pour la même condition entre le premier EXEC SQL WHENEVER et l'instruction SQL qui a engendré la condition, quelque soit le flux de contrôle du programme C. De ce fait, aucun des deux extraits de programme C qui suivent n'aura le comportement désiré.

/*
 * MAUVAIS
 */
int main(int argc, char *argv[])
{
    ...
    if (verbose) {
        EXEC SQL WHENEVER SQLWARNING SQLPRINT;
    }
    ...
    EXEC SQL SELECT ...;
    ...
}
/*
 * MAUVAIS
 */
int main(int argc, char *argv[])
{
    ...
    set_error_handler();
    ...
    EXEC SQL SELECT ...;
    ...
}

static void set_error_handler(void)
{
    EXEC SQL WHENEVER SQLERROR STOP;
}

30.9.2. sqlca

Pour une gestion plus puissante des erreurs, l'interface du SQL embarqué fournit une variable globale de nom sqlca qui a la structure suivante :

struct
{
    char sqlcaid[8];
    long sqlabc;
    long sqlcode;
    struct
    {
        int sqlerrml;
        char sqlerrmc[70];
    } sqlerrm;
    char sqlerrp[8];
    long sqlerrd[6];
    char sqlwarn[8];
    char sqlstate[5];
} sqlca;

(Dans un programme multithreadé, chaque thread obtient automatiquement sa propre copie de sqlca. Ceci fonctionne de façon similaire à la gestion de la variable globale C standard errno.)

sqlca couvre à la fois les avertissements et les erreurs. Si plusieurs avertissements ou erreurs surviennent lors de l'exécution d'une instruction, alors sqlca ne contiendra que les informations relatives à la dernière.

Si aucune erreur ne survient dans la dernière instruction SQL, sqlca.sqlcode vaudra 0 et sqlca.sqlstate vaudra "00000". Si un avertissement ou une erreur a eu lieu, alors sqlca.sqlcode sera négatif et sqlca.sqlstate sera différent de "00000". Un sqlca.sqlcode positif indique une condition sans dommage, telle que « aucune ligne renvoyée par la dernière requête ». sqlcode et sqlstate sont deux schémas de code d'erreur différents ; les détails apparaissent ci-dessous.

Si la dernière instruction SQL a réussi, alors sqlca.sqlerrd[1] contient l'OID de la ligne traitée, si applicable, et sqlca.sqlerrd[2] contient le nombre de lignes traitées ou renvoyées, si applicable à la commande.

Dans le cas d'une erreur ou d'un avertissement, sqlca.sqlerrm.sqlerrmc contiendra une chaîne décrivant l'erreur. Le champ sqlca.sqlerrm.sqlerrml contient la longueur du message d'erreur stocké dans sqlca.sqlerrm.sqlerrmc (le résultat de strlen(), sans réel intérêt pour un programmeur C). Notez que certains messages sont trop longs pour entrer dans le tableau sqlerrmc de taille fixe ; ils seront tronqués.

Dans le cas d'un avertissement, sqlca.sqlwarn[2] est positionné à W. (Dans tous les autres cas, il est positionné à quelque chose de différent de W.) Si sqlca.sqlwarn[1] est positionné à W, alors une valeur a été tronquée lors de son stockage dans une variable hôte. sqlca.sqlwarn[0] est positionné à W si un autre élément est positionné pour indiquer un avertissement.

Les champs sqlcaid, sqlcabc, sqlerrp, et les éléments restant de sqlerrd et sqlwarn ne contiennent actuellement aucune information utile.

La structure sqlca n'est pas définie dans le standard SQL mais elle est implémentée dans plusieurs autres systèmes de bases de données SQL. Leurs définitions sont similaires dans leur esprit, mais l'écriture d'applications portables nécessite une étude attentive des autres implémentations.

30.9.3. SQLSTATE contre SQLCODE

Les champs sqlca.sqlstate et sqlca.sqlcode sont deux schémas différents fournissant des codes d'erreur. Les deux sont dérivés du standard SQL mais SQLCODE est indiqué comme obsolète dans l'édition de SQL-92 du standard et a été supprimé dans les éditions ultérieures. Du coup, les nouvelles applications sont fortement encouragées à utiliser SQLSTATE dans les nouvelles applications.

SQLSTATE est un tableau de cinq caractères. Ces cinq caractères contiennent des chiffres ou des lettres en majuscules représentant les codes de différentes conditions d'erreurs ou d'avertissements. SQLSTATE dispose d'un schéma hiérarchique : les deux premiers caractères indiquent la classe générale de la condition, les trois derniers caractères indiquent une sous-classe de la condition générale. Un état de succès est indiqué par le code 00000. Les codes SQLSTATE sont pour la plupart définis dans le standard SQL. Le serveur PostgreSQL™ supporte nativement les codes d'erreurs SQLSTATE ; du coup, un haut degré de cohérence peut être atteint en utilisant ce schéma de code d'erreur au travers de toutes vos applications. Pour plus d'informations, voir l'Annexe A, Codes d'erreurs de PostgreSQL.

SQLCODE, le schéma obsolète de codes d'erreurs, est un simple entier. Une valeur 0 indique un succès, une valeur positive indique un succès avec des informations supplémentaires, une valeur négative indique une erreur. Le standard SQL définit seulement la valeur positive +100, qui indique que la dernière commande n'a renvoyé ou modifié de ligne, et aucune valeur négative. Du coup, ce schéma n'est que faiblement portable et n'a pas d'affectation de code hiérarchique. Historiquement, le processeur de SQL embarqué pour PostgreSQL™ a affecté quelques valeurs SQLCODE spécifiques pour sa propre utilisation, qui sont listées ci-dessous avec leurs valeurs numériques et leurs noms symboliques. Il est important de garder à l'esprit qu'elles ne sont pas portables vers d'autres implémentations SQL. Pour simplifier le portage d'applications au schéma SQLSTATE, le code SQLSTATE correspondant est également affiché. Néanmoins, il n'y a pas de correspondance une-à-une ou une-à-plusieurs entre les deux schémas (en fait, c'est plutôt plusieurs-à-plusieurs). Il est préférable de consulter le schéma SQLSTATE global dans l'Annexe A, Codes d'erreurs de PostgreSQL pour chaque cas.

Voici les valeurs affectées à SQLCODE :

-12 (ECPG_OUT_OF_MEMORY)

Indique que la mémoire virtuelle est épuisée. (SQLSTATE YE001)

-200 (ECPG_UNSUPPORTED)

Indique que le préprocesseur a engendré quelque chose que la bibliothèque ne connaît pas. Il peut s'agir de l'exécution de versions incompatibles du préprocesseur et de la bibliothèque (SQLSTATE YE002).

-201 (ECPG_TOO_MANY_ARGUMENTS)

Ceci signifie que la commande spécifie plus de variables hôtes que n'en attend la commande (SQLSTATE 07001 ou 07002).

-202 (ECPG_TOO_FEW_ARGUMENTS)

Ceci signifie que la commande spécifie moins de variables hôtes que n'en attend la commande (SQLSTATE 07001 ou 07002).

-203 (ECPG_TOO_MANY_MATCHES)

Ceci signifie qu'une requête a retourné plusieurs lignes mais que l'instruction n'était préparée à ne stocker qu'une ligne de résultat (par exemple, parce que les variables spécifiées ne sont pas des tableaux) (SQLSTATE 21000).

-204 (ECPG_INT_FORMAT)

La variable hôte est de type int, et la donnée de la base de données est d'un type différent et contient une valeur qui ne peut pas être interprétée comme un int. La bibliothèque utilise strtol() pour cette conversion (SQLSTATE 42804).

-205 (ECPG_UINT_FORMAT)

La variable hôte est de type unsigned int, et la donnée de la base de données est d'un type différent et contient une valeur qui ne peut pas être interprétée comme un unsigned int. La bibliothèque utilise strtoul() pour cette conversion (SQLSTATE 42804).

-206 (ECPG_FLOAT_FORMAT)

La variable hôte est de type float, et la donnée de la base de données est d'un type différent et contient une valeur qui ne peut pas être interprétée comme un float. La bibliothèque utilise strtod() pour cette conversion (SQLSTATE 42804).

-211 (ECPG_CONVERT_BOOL)

Ceci signifie que la variable hôte est de type bool et que la donnée de la base de données n'est ni 't' ni 'f' (SQLSTATE 42804).

-212 (ECPG_EMPTY)

L'instruction envoyée au serveur PostgreSQL™ était vide (ceci ne peut normalement pas survenir dans un programme SQL embarqué, cela peut donc indiquer une erreur interne) (SQLSTATE YE002).

-213 (ECPG_MISSING_INDICATOR)

Une valeur NULL a été retournée et aucune variable d'indicateur nul n'a été fournie (SQLSTATE 22002).

-214 (ECPG_NO_ARRAY)

Une variable ordinaire a été utilisée à un endroit qui requiert un tableau (SQLSTATE 42804).

-215 (ECPG_DATA_NOT_ARRAY)

La base de données a retourné une variable ordinaire à un endroit qui requiert une valeur de tableau (SQLSTATE 42804).

-220 (ECPG_NO_CONN)

Le programme a tenté d'accéder à une connexion qui n'existe pas (SQLSTATE 08003).

-221 (ECPG_NOT_CONN)

Le programme a tenté d'accéder à une connexion qui existe mais n'est pas ouverte (ceci est une erreur interne) (SQLSTATE YE002).

-230 (ECPG_INVALID_STMT)

Une tentative d'utilisation d'une instruction qui n'a pas été préparée est survenue (SQLSTATE 26000).

-240 (ECPG_UNKNOWN_DESCRIPTOR)

Le descripteur spécifié n'a pas été trouvé. Une tentative d'utilisation d'une instruction qui n'a pas été préparée est survenue (SQLSTATE 33000).

-241 (ECPG_INVALID_DESCRIPTOR_INDEX)

L'index du descripteur spécifié est hors échelle (SQLSTATE 07009).

-242 (ECPG_UNKNOWN_DESCRIPTOR_ITEM)

Un élément invalide du descripteur a été demandé (ceci est une erreur interne) (SQLSTATE YE002).

-243 (ECPG_VAR_NOT_NUMERIC)

Lors de l'exécution d'une instruction dynamique, la base de données a retourné une valeur numérique et la variable hôte n'était pas numérique (SQLSTATE 07006).

-244 (ECPG_VAR_NOT_CHAR)

Lors de l'exécution d'une instruction dynamique, la base de données a retourné une valeur non numérique et la variable hôte était numérique (SQLSTATE 07006).

-400 (ECPG_PGSQL)

Une erreur a été causée par le serveur PostgreSQL™. Le message contient le message d'erreur du serveur PostgreSQL™.

-401 (ECPG_TRANS)

Le serveur PostgreSQL™ a signalé que la transaction ne peut être commencée, validée ou annulée (SQLSTATE 08007).

-402 (ECPG_CONNECT)

La tentative de connexion à la base de données a échoué (SQLSTATE 08001).

100 (ECPG_NOT_FOUND)

Ceci est une condition sans gravité indiquant que la dernière commande n'a récupéré ou traité aucune ligne, ou que la fin du curseur est atteinte (SQLSTATE 02000).