31.11. 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.
31.11.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 indiquée est appelée lorsqu'une erreur survient
pendant l'exécution d'une instruction SQL ;
-
SQLWARNING
-
l'action indiquée est appelée lorsqu'un avertissement
survient pendant l'exécution d'une instruction SQL ;
-
NOT FOUND
-
l'action indiqué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 prendre une des
valeurs suivantes :
-
CONTINUE
-
la condition est ignorée. C'est le comportement par défaut ;
-
GOTO
label
,
GO TO
label
-
saute au label indiqué (à l'iade d'une instruction C
goto) ;
-
SQLPRINT
-
affiche un message sur la sortie standard. Cela est utile
pour les programmes simples ou lors du prototypage. Les
détails du message ne peuvent pas être configurés ;
-
STOP
-
appelle exit(1), ce qui termine le
programme ;
-
DO BREAK
-
exécute l'instruction C break. Cela
ne doit être utilisé que dans les boucles et les instructions
switch ;
-
CALL
nom
(
args
),
DO
nom
(
args
)
-
appelle les fonctions C indiquées avec les arguments
indiqués.
Le standard SQL ne définit que les actions CONTINUE et GOTO (et
GO TO).
L'exemple suivant est 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
ien cas d'erreur ou d'avertissement 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 engendre 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'a 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;
}
31.11.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 contient que les informations relatives à
la dernière.
Si aucune erreur ne survient dans la dernière instruction
SQL, sqlca.sqlcode vaut 0 et sqlca.sqlstate vaut "00000". Si un avertissement ou une erreur survient,
alors sqlca.sqlcode est négatif et
sqlca.sqlstate est différent de "00000". Une valeur positive de sqlca.sqlcode indique une condition sans dommage,
telle que « la dernière requête n'a
retourné aucune ligne ». 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.
En cas d'erreur ou d'avertissement, sqlca.sqlerrm.sqlerrmc contient 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).
Certains messages sont trop longs pour entrer dans le tableau
sqlerrmc de taille fixe ; ils sont alors
tronqués.
En cas d'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 tout 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 implantée dans plusieurs autres
systèmes de bases de données SQL. Leurs définitions sont similaires
dans l'esprit, mais l'écriture d'applications portables nécessite
une étude attentive des autres implantations.
31.11.3. SQLSTATE vs 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 SQL-92 du standard et a été supprimé dans
les éditions ultérieures. C'est pourquoi il est fortement
recommandé que les nouvelles applications utilisent 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 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 ;
de ce fait, un haut degré de cohérence peut être atteint en
utilisant ce schéma de code d'erreur dans toutes les applications.
Pour plus d'informations, voir l'Annexe A,
Codes d'erreurs de PostgreSQL™.
SQLCODE, 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 ne définit que la valeur positive +100, qui indique
que la dernière commande n'a renvoyé ou modifié aucune ligne, et
aucune valeur négative spécifique. De ce fait, ce schéma n'est que
faiblement portable et ne propose 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. ces valeurs sont listées ci-dessous
avec leurs valeurs numériques et leurs noms symboliques. Elles ne
sont pas portables vers d'autres implémentations SQL. Pour
simplifier le portage d'applications vers la schéma SQLSTATE, le code SQLSTATE
correspondant est également affiché. Il n'y a toutefois 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.
Valeurs affectées à SQLCODE :
-
-12 (ECPG_OUT_OF_MEMORY)
-
la mémoire virtuelle est épuisée, (SQLSTATE YE001) ;
-
-200 (ECPG_UNSUPPORTED)
-
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)
-
la commande indique plus de variables hôtes que n'en attend
la commande (SQLSTATE 07001 ou 07002) ;
-
-202 (ECPG_TOO_FEW_ARGUMENTS)
-
la commande indique moins de variables hôtes que n'en attend
la commande (SQLSTATE 07001 ou 07002) ;
-
-203 (ECPG_TOO_MANY_MATCHES)
-
une requête retourne plusieurs lignes alors que l'instruction
n'est préparée à ne stocker qu'une seule ligne de résultat
(par exemple, parce que les variables indiquées ne sont pas
des tableaux) (SQLSTATE 21000) ;
-
-204 (ECPG_INT_FORMAT)
-
la variable hôte est de type int
alors que la donnée dans la base 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 alors que la donnée de la base 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
alors que la donnée de la base 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) ;
-
-207 (ECPG_CONVERT_BOOL)
-
la variable hôte est de type bool
alors que la donnée de la base n'est ni 't' ni 'f' (SQLSTATE
42804) ;
-
-208 (ECPG_EMPTY)
-
l'instruction envoyée au serveur PostgreSQL™ est vide (ceci ne peut
normalement pas survenir dans un programme SQL embarqué, cela
peut donc indiquer une erreur interne) (SQLSTATE YE002) ;
-
-209 (ECPG_MISSING_INDICATOR)
-
une valeur NULL est retournée alors qu'aucune variable
indicateur de nullité n'est fournie (SQLSTATE 22002) ;
-
-210 (ECPG_NO_ARRAY)
-
une variable ordinaire est utilisée à un endroit qui requiert
un tableau (SQLSTATE 42804) ;
-
-211 (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 tente d'accéder à une connexion qui n'existe pas
(SQLSTATE 08003) ;
-
-221 (ECPG_NOT_CONN)
-
le programme tente d'accéder à une connexion qui existe mais
n'est pas ouverte (ceci est une erreur interne) (SQLSTATE
YE002) ;
-
-230 (ECPG_INVALID_STMT)
-
l'instruction utilisée n'a pas été préparée (SQLSTATE 26000)
;
-
-240 (ECPG_UNKNOWN_DESCRIPTOR)
-
le descripteur indiqué n'a pas été trouvé. L'instruction
utilisée n'a pas été préparée (SQLSTATE 33000) ;
-
-241 (ECPG_INVALID_DESCRIPTOR_INDEX)
-
l'index du descripteur indiqué est hors échelle (SQLSTATE
07009) ;
-
-242 (ECPG_UNKNOWN_DESCRIPTOR_ITEM)
-
un élément invalide du descripteur est 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 alors que la variable
hôte n'est 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 alors que la
variable hôte est numérique (SQLSTATE 07006) ;
-
-400 (ECPG_PGSQL)
-
le serveur PostgreSQL™
a engendré une erreur. Le message contient le message
d'erreur du serveur PostgreSQL™ ;
-
-401 (ECPG_TRANS)
-
le serveur PostgreSQL™
signale 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)
-
il s'agit d'une condition sans gravité qui indique que la
dernière commande n'a récupéré ou traité aucune ligne, ou que
la fin du curseur est atteinte (SQLSTATE 02000).