Documentation PostgreSQL 7.4.29 | ||||
---|---|---|---|---|
Pr�c�dent | Arri�re rapide | Chapitre 27. libpq - Biblioth�que C | Avance rapide | Suivant |
La fonction PQexec
est parfaite pour soumettre des
commandes aux applications standards, synchrones. N�anmoins, elle a quelques
d�ficiences qui peuvent �tre importantes pour certaines utilisateurs :
PQexec
attend que la commande se termine. L'application
pourrait avoir d'autres travaux � r�aliser (comme le rafraichissement de
l'interface utilisateur), auquel cas il ne voudra pas �tre bloqu� en attente
de la r�ponse.
Comme l'ex�cution de l'application cliente est suspendue en attendant le r�sultat, il est difficile pour l'application de d�cider qu'elle voudrait annuler la commande en cours. (C'est possible avec un gestionnaire de signaux mais pas autrement.)
PQexec
ne peut renvoyer qu'une structure
PGresult. Si la cha�ne de commande soumise contient
plusieurs commandes SQL, toutes les structures
PGresult sont annul�es par
PQexec
, sauf la derni�re.
Les applications qui n'appr�cient pas ces limitations peuvent utiliser � la
place les fonctions sous-jacentes � partir desquelles
PQexec
est construite :
PQsendQuery
et PQgetResult
. Il existe
aussi PQsendQueryParams
et
PQsendQueryPrepared
, pouvant �tre utilis�es avec
PQgetResult
pour dupliquer les fonctionnalit�s de
respectivement PQexecParams
et
PQexecPrepared
.
PQsendQuery
Soumet une commande au serveur sans attendre le(s) r�sultat(s). 1 est
renvoy� si la commande a �t� correctement envoy�e et 0 sinon (dans ce
cas, utilisez la fonction PQerrorMessage
pour obtenir
plus d'informations sur l'�chec).
int PQsendQuery(PGconn *conn, const char *command);
Apr�s un appel r�ussi � PQsendQuery
, appelez
PQgetResult
une ou plusieurs fois pour obtenir
les r�sultats. PQsendQuery
ne peut �tre appel�e
de nouveau (sur la m�me connexion) tant que
PQgetResult
n'a pas renvoy� un pointeur nul,
indiquant que la commande est termin�e.
PQsendQueryParams
Soumet une commande et des param�tres s�par�s au serveur sans attendre le(s) r�sultat(s).
int PQsendQueryParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char * const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat);
Ceci est �quivalent � PQsendQuery
sauf que les
param�tres de requ�tes peuvent �tre sp�cifi�s s�par�ment de la cha�ne de
requ�te. Les param�tres de la fonction sont g�r�s de fa�on identique �
PQexecParams
. Comme
PQexecParams
, PQsendQueryParams
ne fonctionne pas pour les connexions utilisant le protocole 2.0 et
ne permet qu'une seule commande dans la cha�ne de requ�te.
PQsendQueryPrepared
Envoie une requ�te pour ex�cuter une instruction pr�par�e, avec les param�tres donn�s, sans attendre le(s) r�sultat(s).
int PQsendQueryPrepared(PGconn *conn, const char *stmtName, int nParams, const char * const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat);
Cette fonction est similaire � PQsendQueryParams
mais la
commande � ex�cuter est sp�cifi�e en nommant une instruction
pr�c�demment pr�par�e au lieu de donner une cha�ne contenant la
requ�te. Les param�tres de la fonction sont g�r�s de fa�on identique �
PQexecPrepared
. Comme
PQexecPrepared
, PQsendQueryPrepared
ne fonctionne pas pour les connexions utilisant le protocole 2.0.
PQgetResult
Attend le prochain r�sultat d'un appel pr�c�dent �
PQsendQuery
,
PQsendQueryParams
ou
PQsendQueryPrepared
, et le renvoie. Un pointeur
nul est renvoy� quand la commande est termin�e et qu'il n'y aura plus
de r�sultats.
PGresult *PQgetResult(PGconn *conn);
PQgetResult
doit �tre appel�e de fa�on r�p�t�e
jusqu'� ce qu'elle retourne un pointeur nul indiquant que la commande
s'est termin�e. (Si elle est appel�e � un moment o� aucune commande n'est
active, PQgetResult
renvoie un
pointeur nul d�s la premi�re fois.) Chaque r�sultat non nul provenant de
PQgetResult
doit �tre trait� en utilisant les
m�mes fonctions d'acc�s � PGresult que celles
pr�c�demment d�crites. N'oubliez pas de lib�rer chaque objet r�sultat
avec PQclear
une fois que vous en avez termin�.
Notez que PQgetResult
bloque seulement si la
commande est active et que les donn�es n�cessaires en r�ponse n'ont
pas encore �t� lues par PQconsumeInput
.
Utiliser PQsendQuery
et PQgetResult
r�sout un des probl�mes de PQexec
: si une cha�ne de
commande contient plusieurs commandes SQL, les r�sultats de
ces commandes peuvent �tre obtenus individuellement. (Ceci permet une forme
simple de traitement en parall�le : le client peut g�rer les r�sultats
d'une commande alors que le serveur travaille sur d'autres requ�tes de la m�me
cha�ne de commandes.) N�anmoins, appeler PQgetResult
cause toujours un blocage du client jusqu'� la fin de la prochaine commande
SQL. Ceci est �vitable en utilisant proprement deux
fonctions suppl�mentaires :
PQconsumeInput
Si une entr�e est disponible � partir du serveur, elle est consomm�e.
int PQconsumeInput(PGconn *conn);
PQconsumeInput
renvoie normalement 1 ce qui indique
<<�aucune erreur�>>, mais renvoie z�ro s'il y a eu une erreur (auquel
cas PQerrorMessage
peut �tre consult�e). Notez que le
r�sultat ne dit pas si des donn�es ont �t� r�cup�r�es en entr�es. Apr�s avoir
appel� PQconsumeInput
, l'application doit v�rifier
PQisBusy
et/ou PQnotifies
pour voir
si leur �tat a chang�.
PQconsumeInput
peut �tre appel�e m�me si l'application
n'est pas encore pr�par� � g�rer un r�sultat ou une notification. La fonction
lit les donn�es disponibles et les sauvegarde dans un tampon, ce qui remet � z�ro
l'indication qu'une lecture de select()
est disponible.
L'application peut donc utiliser PQconsumeInput
pour
effacer la condition select()
imm�diatement, puis
examiner les r�sultats plus tard � sa guise.
PQisBusy
Renvoie 1 si une commande est occup�e, c'est-�-dire si
PQgetResult
bloquerait en attendant une entr�e. Un z�ro
indique que PQgetResult
peut �tre appel�e avec
l'assurance de ne pas �tre bloqu�e.
int PQisBusy(PGconn *conn);
PQisBusy
ne tente pas elle-m�me de lire les donn�es �
partir du serveur ; du coup, PQconsumeInput
doit �tre
appel�e d'abord, sans quoi l'�tat occup� ne s'arr�tera jamais.
Une application typique de l'utilisation des ces fonctions a une boucle
principale utilisant select()
ou poll()
pour
attendre toutes les conditions auxquelles elle doit r�pondre. Une des conditions
est que des donn�es sont disponibles � partir du serveur, ce qui signifie pour
select()
des donn�es lisibles sur le descripteur de
fichier identifi� par PQsocket
. Lorsque la boucle
principale d�tecte la disponibilit� de donn�es, elle doit appeler
PQconsumeInput
pour lire l'ent�te. Elle peut ensuite appeler
PQisBusy
puis PQgetResult
si
PQisBusy
renvoie false (0). Elle peut aussi appeler
PQnotifies
pour d�tecter les messages NOTIFY
(voir Section 27.6).
Un client qui utilise
PQsendQuery
/PQgetResult
peut aussi
tenter d'annuler une commande en cours de traitement par le
serveur.
PQrequestCancel
Demande au serveur d'abandonner le traitement de la commande en cours.
int PQrequestCancel(PGconn *conn);
Le code de retour est 1 si la demande d'annulation a �t� correctement envoy�e
et 0 sinon. (Si non, PQerrorMessage
dira pourquoi.) Un
envoi correct ne garantit pas que la demande aura un effet. Quel que soit le
code de retour de PQrequestCancel
, l'application doit
continuer la s�quence normale de lecture/r�sultat en utilisant
PQgetResult
. Si l'annulation est r�elle, la commande
en cours se termine rapidement et renvoie un r�sultat d'erreur. Si l'annulation
�choue (par exemple parce que le serveur a d�j� termin� l'ex�cution de la
commande), aucun r�sultat n'est visible.
Notez que si la commande en cours fait partie d'un bloc de transaction, l'annulation est effective pour la transaction compl�te.
PQrequestCancel
peut �tre appel�e en toute s�curit� depuis
un gestionnaire de signaux. Donc, il est aussi possible de l'utiliser avec des
PQexec
, si la d�cision d'annuler doit �tre faite dans un
gestionnaire de signaux. Par exemple, psql appelle
PQrequestCancel
� partir du gestionnaire du signal
SIGINT, autorisant du coup l'annulation interactive des commandes
qu'il envoie via PQexec
.
En utilisant les fonctions d�crites ci-dessus, il est possible d'�viter le blocage pendant l'attente de donn�es du serveur. N�anmoins, il est toujours possible que l'application se bloque en attendant l'envoi vers le serveur. C'est relativement peu fr�quent mais cela peut arriver si de tr�s longues commandes SQL ou donn�es sont envoy�es. (C'est bien plus probable si l'application envoie des donn�es via COPY IN.) Pour emp�cher cette possibilit� et r�ussir des op�rations de bases de donn�es totalement non bloquantes, les fonctions suppl�mentaires suivantes peuvent �tre utilis�es.
PQsetnonblocking
Initialise le statut non bloquant de la connexion.
int PQsetnonblocking(PGconn *conn, int arg);
Initialise l'�tat de la connexion � non bloquant si arg vaut 1 et � bloquant si arg vaut 0. Renvoie 0 si OK, -1 en cas d'erreur.
Dans l'�tat non bloquant, les appels �
PQsendQuery
,
PQputline
, PQputnbytes
,
et PQendcopy
ne bloquent pas mais renvoient � la
place une erreur s'ils ont besoin d'�tre de nouveau appel�s.
Notez que PQexec
n'honore pas le mode non
bloquant ; si elle est appel�e, elle agira d'une fa�on bloquante
malgr� tout.
PQisnonblocking
Renvoie le statut bloquant ou non de la connexion � la base de donn�es.
int PQisnonblocking(const PGconn *conn);
Renvoie 1 si la connexion est en mode non bloquant, 0 dans le cas contraire.
PQflush
Tente de vider les donn�es en attente d'envoi vers le serveur. Renvoie 0 en cas de succ�s (ou si la queue d'envoi est vide), -1 en cas d'�chec quelle que soit la raison ou 1 si elle n'a pas encore pu envoyer toutes les donn�es dans la queue d'envoi (ce cas arrive seulement si la connexion est non bloquante).
int PQflush(PGconn *conn);
Apr�s avoir envoy� une commande ou des donn�es dans une connexion non bloquante,
appelez PQflush
. Si elle renvoie 1, attendez que la socket
soit disponible en �criture et appelez-la de nouveau ; r�p�tez cela jusqu'�
ce qu'elle renvoie 0. Une fois que PQflush
renvoie 0,
attendez que la socket soit disponible en lecture puis lisez la r�ponse comme
d�crit ci-dessus.
Pr�c�dent | Sommaire | Suivant |
Fonctions de commandes d'ex�cution | Niveau sup�rieur | Interface � chemin rapide |