Documentation PostgreSQL 7.4.29 | ||||
---|---|---|---|---|
Précédent | Arrière rapide | Chapitre 27. libpq - Bibliothèque C | Avance rapide | Suivant |
La commande COPY dans PostgreSQL a des options pour lire ou écrire à partir de la connexion réseau utilisée par libpq. Les fonctions décrites dans cette section permettent aux applications d'utiliser cette capacité en apportant ou en consommant des données copiées.
Le processus complet de COPY est le suivant:
L'application lance tout d'abord la commande SQL
COPY via PQexec
ou une des fonctions
équivalentes. La réponse à ceci (s'il n'y a pas d'erreur dans la commande) est
un objet PGresult avec un code de retour
PGRES_COPY_OUT ou PGRES_COPY_IN (suivant
la direction spécifiée pour la copie). L'application doit alors utiliser les
fonctions de cette section pour recevoir ou transmettre des lignes de données.
Quand le transfert de données est terminé, un autre objet
PGresult est renvoyé pour indiquer le succès ou l'échec du
transfert. Son statut est PGRES_COMMAND_OK en cas de succès
et PGRES_FATAL_ERROR si un problème a été rencontré. À ce
moment seulement, une autre commande SQL peut être lancée via
PQexec
. (Il n'est pas possible d'exécuter d'autres
commandes SQL en utilisant la même connexion tant que l'opération
COPY est en cours.)
Si une commande COPY est lancée via
PQexec
dans une chaîne qui pourrait contenir d'autres
commandes supplémentaires, l'application doit continuer à récupérer les
résultats via PQgetResult
après avoir terminé la séquence
COPY. C'est seulement quand PQgetResult
renvoie
NULL que vous pouvez être certain que la chaîne de commandes
PQexec
est terminée et qu'il est possible de lancer
d'autres commandes.
Les fonctions de cette section ne doivent être exécutées qu'après avoir obtenu
un statut de résultat PGRES_COPY_OUT ou
PGRES_COPY_IN à partir de PQexec
ou
PQgetResult
.
Un objet PGresult contenant un de ces statuts comporte quelques données supplémentaires sur l'opération COPY qui commence. La données supplémentaire est disponible en utilisant les fonctions qui sont aussi utilisées en relation avec les résultats de requêtes :
PQnfields
Renvoie le nombre de colonnes (champs) à copier.
PQbinaryTuples
0 indique que le format de copie complet est textuel (lignes séparées par des retours chariots, colonnes séparées par des caractères de séparation, etc). 1 indique que le format de copie complet est binaire. Voir COPY pour plus d'informations.
PQfformat
Renvoie le code de format (0 pour le texte, 1 pour le binaire) associé à chaque colonne de l'opération de copie. Les codes de format par colonne sont toujours zéro si le format de copie complet est textuel mais le format binaire supporte à la fois des colonnes textuelles et des colonnes binaires. (Néanmoins, avec l'implémentation actuelle de COPY, seules des colonnes binaires apparaissent dans une copie binaire donc actuellement, les formats par colonnes correspondent toujours au format complet.)
Note : Ces valeurs de données supplémentaires sont seulement disponibles en utilisant le protocole 3.0. Lors de l'utilisation du protocole 2.0, toutes ces fonctions renvoient 0.
Ces fonctions sont utilisées pour envoyer des données lors d'un COPY FROM STDIN. Elles échouent si elles sont appelées alors que la connexion ne se trouve pas dans l'état COPY_IN.
PQputCopyData
Envoie des données au serveur pendant un état COPY_IN.
int PQputCopyData(PGconn *conn, const char *buffer, int nbytes);
Transmet les données de COPY du buffer
spécifié, sur nbytesoctets, au serveur. Le résultat vaut 1 si les
données ont été envoyées, zéro si elles n'ont pas été envoyées car la tentative
pourrait bloquer (ce cas n'est possible que dans le cas d'une connexion en mode
non bloquant) ou -1 si une erreur s'est produite. (Utilisez
PQerrorMessage
pour récupérer des détails si la valeur de
retour vaut -1. Si la valeur vaut zéro, attendez que la connexion soit disponible
en écriture et ré-essayez.)
L'application peut diviser le flux de données de COPY en tampons de taille quelconque. Les tailles de tampons n'ont pas de signification sémantique lors de l'envoi. Le contenu du flux de données doit correspondre au format de données attendu par la commande COPY ; voir COPY pour des détails.
PQputCopyEnd
Envoie une indication de fin de transfert au serveur lors de l'état COPY_IN.
int PQputCopyEnd(PGconn *conn, const char *errormsg);
Termine l'opération COPY_IN avec succès si errormsg est NULL. Si errormsg n'est pas NULL alors COPY échoue, la chaîne pointée par errormsg étant utilisée comme message d'erreur. Il ne faut pas supposer que ce message d'erreur précis reviendra du serveur car le serveur peut avoir déjà échouée sur la commande COPY pour des raisons qui lui sont propres. Notez aussi que l'option forçant l'échec ne fonctionne pas lors de l'utilisation de connexions avec un protocole pre-3.0.
Le résultat est 1 si les données de fin ont été envoyées, zéro si elles ne l'ont
pas été car cette tentative serait bloquante (ce cas est uniquement possible
si la connexion est dans un mode non bloquant) ou -1 si une erreur est survenue.
(Utilisez PQerrorMessage
pour récupérer les détails si le
code de retour est -1. Si la valeur vaut zéro, attendez que le serveur
soit prêt en écriture et ré-essayez de nouveau.)
Après un appel réussi à PQputCopyEnd
, appelez
PQgetResult
pour obtenir le statut de résultat final de la commande
COPY. Vous pourriez attendre que le résultat soit disponible de la
même façon. Puis, retournez aux opérations normales.
Ces fonctions sont utilisées pour recevoir des données lors d'un COPY TO STDOUT. Elles échouent si elles sont appelées alors que la connexion n'est pas dans l'état COPY_OUT
PQgetCopyData
Reçoit des données du serveur lors d'un état COPY_OUT.
int PQgetCopyData(PGconn *conn, char **buffer, int async);
Tente d'obtenir une autre ligne de données du serveur lors d'une
opération COPY. Les données ne sont renvoyées qu'une ligne à
la fois ; si seule une ligne partielle est disponible, elle n'est pas
renvoyée. Le retour d'une ligne avec succès implique l'allocation d'une portion
de mémoire pour contenir les données. Le paramètre buffer ne doit
pas être NULL. *buffer est initialisé pour
pointer vers la mémoire allouée ou vers NULL au cas où aucun
tampon n'est renvoyé. Un tampon résultat non NULL doit être
libéré en utilisant PQfreemem
lorsqu'il n'est plus utile.
Lorsqu'une ligne est renvoyée avec succès, le code de retour est le
nombre d'octets de la donnée dans la ligne (et est donc supérieur
à zéro). La chaîne renvoyée est toujours terminée par un octet nul bien que ce
ne soit utile que pour les COPY textuels. Un résultat
zéro indique que la commande COPY est toujours en cours mais
qu'aucune ligne n'est encore disponible (ceci n'est possible que lorsque
async est vrai). Un résultat de -1 indique que
COPY a terminé. Un résultat de -2 indique qu'une erreur est
survenue (consultez PQerrorMessage
pour en connaître la raison).
Lorsque async est vrai (différent de zéro),
PQgetCopyData
ne bloque pas en attente d'entrée ; elle
renvoie zéro si COPY est toujours en cours mais qu'aucune
ligne n'est encore disponible. Dans ce cas, attendez que le connexion soit prête
en lecture puis appelez PQconsumeInput
avant d'appeler de
nouveau PQgetCopyData
). Quand async est faux (zéro),
PQgetCopyData
bloque tant que les données ne sont pas disponibles
ou tant que l'opération n'est pas terminée.
Après que PQgetCopyData
ait renvoyé -1, appelez
PQgetResult
pour obtenir le statut de résultat final de la commande
COPY. Vous pourriez attendre la disponibilité de ce résultat, comme
d'habitude. Puis, retournez aux opérations habituelles.
Ces fonctions représentent d'anciennes méthodes de gestion de COPY. Bien qu'elles fonctionnent toujours, elles sont obsolètes à cause de leur médiocre gestion des erreurs, des méthodes peu commodes de détection d'une fin de transmission, et de l'absence de support des transferts binaires et des transferts non bloquants.
PQgetline
Lit une ligne de caractères terminée par un retour chariot (transmise par le serveur) dans un tampon de taille length.
int PQgetline(PGconn *conn, char *buffer, int length);
Cette fonction copie jusqu'à length-1 caractères dans le tampin
et convertit le retour chariot en un octet nul. PQgetline
renvoie EOF à la fin de l'entrée, 0 si la ligne entière a été
lu et 1 si le tampon est complet mais que le retour chariot à la fin n'a pas
encore été lu.
Notez que l'application doit vérifier si un retour chariot est constitué de deux caractères \., ce qui indique que le serveur a terminé l'envoi des résultats de la commande COPY. Si l'application peut recevoir des lignes de plus de length-1 caractères, une attention toute particulière est nécessaire pour s'assurer qu'elle reconnaisse la ligne \. correctement (et ne la confonde pas, par exemple, avec la fin d'une longue ligne de données).
PQgetlineAsync
Lit une ligne de données COPY (transmise par le serveur) dans un tampon sans blocage.
int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize);
Cette fonction est similaire à PQgetline
mais elle peut
être utilisée par des applications qui doivent lire les données de
COPY de façon asynchrone, c'est-à-dire sans blocage. Après
avoir lancé la commande COPY et obtenu une réponse
PGRES_COPY_OUT, l'application doit appeler
PQconsumeInput
et
PQgetlineAsync
jusqu'à ce que le signal de fin de données
soit détecté.
Contrairement à PQgetline
, cette fonction prend la
responsabilité de détecter la fin de données.
À chaque appel, PQgetlineAsync
renvoie des données si une
ligne de données complète est disponible dans le tampon d'entrée de
libpq. Sinon, aucune ligne n'est renvoyée jusqu'à l'arrivée du
reste de la ligne. La fonction renvoie -1 si le marqueur de fin de copie des
données a été reconnu ou 0 si aucune donnée n'est disponible ou un nombre
positif indiquant le nombre d'octets renvoyés. Si -1 est renvoyé, l'appeleur
doit ensuite appeler PQendcopy
puis retourner aux
traitements habituels.
Les données renvoyées ne renvoie pas plus d'une ligne à la fois. Si possible, une ligne complète est retournée en une fois. Mais si le tampon offert par l'appelant est trop petit pour contenir une ligne envoyée par le serveur, alors une ligne de données partielle est renvoyée. Avec des données textuelles, ceci peut être détecté en testant si le dernier octet renvoyé est \n ou non. (Dans un COPY binaire, l'analyse réelle du format de données COPY est nécessaire pour faire la détermination équivalente.) La chaîne renvoyée n'est pas terminée par un octet nul. (Si vous voulez ajouter un octet nul de terminaison, assurez-vous de passer un bufsize inférieur de 1 par rapport à l'espace réellement disponible.)
PQputline
Envoie une chaîne terminée par un octet nul au serveur. Renvoie 0 si tout va bien et EOF s'il est incapable d'envoyer la chaîne.
int PQputline(PGconn *conn, const char *string);
Le flux de données de COPY envoyé par une série d'appels à
PQputline
a le même format que celui renvoyé par
PQgetlineAsync
, sauf que les applications ne sont pas
obligées d'envoyer exactement une ligne de données par appel à
PQputline
; il est possible d'envoyer une ligne
partielle ou plusieurs lignes par appel.
Note : Avant le protocole 3.0 de PostgreSQL, il était nécessaire que l'application envoie explicitement les deux caractères \. comme ligne finale pour indiquer la fin de l'envoi des données du COPY data. Bien que ceci fonctionne toujours, cette méthode est abandonnée et la signification spéciale de \. pourrait être supprimée dans une prochaine version. Il est suffisant d'appeler
PQendcopy
après avoir envoyé les vraies données.
PQputnbytes
Envoie une chaîne non terminée par un octet nul au serveur. Renvoie 0 si tout va bien et EOF s'il n'a pas été possible d'envoyer la chaîne.
int PQputnbytes(PGconn *conn, const char *buffer, int nbytes);
C'est exactement comme PQputline
sauf que le tampon de
données n'a pas besoin d'être terminé avec un octet nul car le nombre d'octets
envoyés est indiqué directement. Utilisez cette procédure pour envoyer des
données binaires.
PQendcopy
Se synchronise avec le serveur.
int PQendcopy(PGconn *conn);
Cette fonction attend jusqu'à ce que le serveur ait terminé la copie.
Elle doit être appelée
pour indiquer quand la dernière chaîne a été envoyée au serveur en utilisant
PQputline
ou quand la dernière chaîne a été reçue
du serveur en utilisant PGgetline
. Si
PQendcopy
est omise, le serveur se << désynchronisera >>
du client. Au retour de cette fonction, le serveur est
prêt à recevoir la prochaine commande SQL. Le code de retour 0 indique un
succès et est différent de zéro dans le cas contraire. (Utilisez
PQerrorMessage
pour récupérer des détails sur l'échec.)
Lors de l'utilisation de PQgetResult
, l'application
doit répondre à un résultat PGRES_COPY_OUT en exécutant
PQgetline
de façon répétée, suivie par un
PQendcopy
une fois la ligne de terminaison reçue.
Il doit ensuite retourner à la boucle PQgetResult
jusqu'à ce que PQgetResult
renvoie un pointeur nul. De
façon similaire un résultat PGRES_COPY_IN est traité par une
série d'appels à PQputline
suivis par un
PQendcopy
, ensuite retour à la boucle
PQgetResult
. Cette vous assure qu'une commande
COPY intégrée dans une série de commandes
SQL est exécutée correctement.
Les anciennes applications soumettaient un COPY via
PQexec
et assument que la transaction est terminée après un
PQendcopy
. Ceci fonctionne toujours correctement
si et seulement si
COPY est la seule commande SQL dans la
chaîne de commandes.
Précédent | Sommaire | Suivant |
Notification asynchrone | Niveau supérieur | Fonctions de contrôle |