Cette section décrit les possibilités de la bibliothèque d'interface client
libpq de PostgreSQL
permettant d'accéder aux « Large Objects ». L'interface des « Large Objects »
de PostgreSQL est modelé d'après l'interface des
systèmes de fichiers d'Unix avec des analogies pour les
appels open
, read
,
write
, lseek
, etc.
Toutes les manipulations de « Large Objects » utilisant ces fonctions doivent prendre place dans un bloc de transaction SQL car les descripteurs de fichiers des « Large Objects » sont seulement valides pour la durée d'une transaction.
Si une erreur survient lors de l'exécution de ces fonctions, la fonction
renverra une valeur autrement impossible, typiquement 0 or -1. Un message
décrivant l'erreur est stocké dans l'objet de connexion et peut être
récupéré avec la fonction PQerrorMessage
.
Les applications clientes qui utilisent ces fonctions doivent inclure le
fichier d'en-tête libpq/libpq-fs.h
et établir un lien
avec la bibliothèque libpq.
Oid lo_creat(PGconn *conn, int mode);
crée un nouvel objet large. La valeur de retour est un OID assigné au
nouvel objet large ou InvalidOid
(zéro) en cas d'erreur.
mode
est inutilisée et
ignorée sur PostgreSQL 8.1 ; néanmoins,
pour la compatibilité avec les anciennes versions, il est préférable de
l'initialiser à INV_READ
, INV_WRITE
,
ou INV_READ
|
INV_WRITE
(ces constantes symboliques sont définies dans le fichier d'en-tête
libpq/libpq-fs.h
).
Un exemple :
inv_oid = lo_creat(conn, INV_READ|INV_WRITE);
Oid lo_create(PGconn *conn, Oid lobjId);
crée aussi un nouvel objet large. L'OID à affecter peut être spécifié par
lobjId
; dans ce cas, un
échec survient si l'OID est déjà utilisé pour un autre objet large. Si
lobjId
vaut InvalidOid
(zero), alors lo_create
affecte un OID inutilisé (ceci est le
même comportement que lo_creat
). La valeur de retour est
l'OID qui a été affecté au nouvel objet large ou InvalidOid
(zero) en cas
d'échec.
lo_create
est nouveau depuis
PostgreSQL 8.1 ; si cette fonction est
utilisée à partir d'un serveur d'une version plus ancienne, elle échouera
et renverra InvalidOid
.
Un exemple :
inv_oid = lo_create(conn, desired_oid);
Pour importer un fichier du système d'exploitation en tant qu'objet large, appelez
Oid lo_import(PGconn *conn, const char *filename);
filename
spécifie le nom du fichier à importer comme objet large. Le code de retour
est l'OID assigné au nouvel objet large ou InvalidOid
(zero) en cas
d'échec. Notez que le fichier est lu par la bibliothèque d'interface du
client, pas par le serveur. Donc il doit exister dans le système de fichier
du client et lisible par l'application du client.
Oid lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId);
importe aussi un nouvel « large object ». L'OID à affecter peut
être indiqué par lobjId
;
dans ce cas, un échec survient si l'OID est déjà utilisé pour un autre
« large object ». Si lobjId
vaut InvalidOid
(zéro) alors
lo_import_with_oid
affecte un OID inutilisé (et donc
obtient ainsi le même comportement que lo_import
).
La valeur de retour est l'OID qui a été affecté au nouveau « large
object » ou InvalidOid
(zéro) en cas d'échec.
lo_import_with_oid
est une nouveauté de
PostgreSQL 8.4, et utilise en interne
lo_create
qui était une nouveauté de la 8.1 ; si
cette fonction est exécutée sur un serveur en 8.0 voire une version
précédente, elle échouera et renverra InvalidOid
.
Pour exporter un objet large en tant que fichier du système d'exploitation, appelez
int lo_export(PGconn *conn, Oid lobjId, const char *filename);
L'argument lobjId
spécifie l'OID de l'objet large à
exporter et l'argument filename
spécifie le nom du
fichier. Notez que le fichier est écrit par la bibliothèque d'interface du
client, pas par le serveur. Renvoie 1 en cas de succès, -1 en cas d'échec.
Pour ouvrir un objet large existant pour lire ou écrire, appelez
int lo_open(PGconn *conn, Oid lobjId, int mode);
L'argument lobjId
spécifie l'OID de l'objet large à
ouvrir. Les bits mode
contrôlent si l'objet est
ouvert en lecture (INV_READ
), écriture
(INV_WRITE
) ou les deux (ces constantes symboliques
sont définies dans le fichier d'en-tête
libpq/libpq-fs.h
). lo_open
renvoie un
descripteur (positif) d'objet large pour une utilisation future avec
lo_read
, lo_write
,
lo_lseek
, lo_lseek64
,
lo_tell
,
lo_tell64
, lo_truncate
,
lo_truncate64
et lo_close
.
Le descripteur est uniquement valide pour
la durée de la transaction en cours. En cas d'échec, -1 est renvoyé.
Actuellement, le serveur ne fait pas de distinction entre les modes
INV_WRITE
et INV_READ
|
INV_WRITE
: vous êtes autorisé à lire à partir du
descripteur dans les deux cas. Néanmoins, il existe une différence
significative entre ces modes et INV_READ
seul : avec
INV_READ
, vous ne pouvez pas écrire sur le descripteur et la
donnée lue à partir de ce dernier, reflètera le contenu de l'objet large
au moment où lo_open
a été exécuté dans la transaction active,
quelques soient les possibles écritures par cette transaction ou par
d'autres. Lire à partir d'un descripteur ouvert avec
INV_WRITE
renvoie des données reflétant toutes les
écritures des autres transactions validées ainsi que les écritures de la
transaction en cours. Ceci est similaire à la différence de comportement
entre les modes de transaction REPEATABLE READ
et READ
COMMITTED
pour les requêtes SQL SELECT
.
lo_open
échouera si le droit
SELECT
n'est pas disponible pour le Large Object ou si
INV_WRITE
est indiqué et que le droit
UPDATE
n'est pas disponible. (Avant
PostgreSQL 11, ces vérifications de droit
étaient réalisée pour la première vraie lecture ou écriture utilisant ce
descripteur.) Ces vérifications de droit peuvent être désactivées avec le
paramètre lo_compat_privileges.
Un exemple :
inv_fd = lo_open(conn, inv_oid, INV_READ|INV_WRITE);
int lo_write(PGconn *conn, int fd, const char *buf, size_t len);
écrit len
octets à partir de
buf
(qui doit avoir len
comme
taille) dans le descripteur fd
du « Large Object ».
L'argument fd
doit avoir été renvoyé par un appel
précédent à lo_open
. Le nombre d'octets réellement
écrit est renvoyé (dans l'implémentation actuelle, c'est toujours égal
à len
sauf en cas d'erreur). Dans le cas d'une erreur,
la valeur de retour est -1.
Bien que le paramètre len
est déclaré
size_t
, cette fonction rejettera les valeurs plus grandes que
INT_MAX
. En pratique, il est préférable de transférer les
données en plusieurs parties d'au plus quelques méga-octets.
int lo_read(PGconn *conn, int fd, char *buf, size_t len);
lit jusqu'à len
octets à partir du descripteur de
fichier fd
dans buf
(qui
doit avoir pour taille len
). L'argument
fd
doit avoir été renvoyé par un appel précédent à
lo_open
. Le nombre d'octets réellement
lus est renvoyé. Cela sera plus petit que len
si
la fin du « Large Object » est atteint avant. Dans le cas d'une erreur,
la valeur de retour est -1.
Bien que le paramètre len
est déclaré
size_t
, cette fonction rejettera les valeurs plus grandes que
INT_MAX
. En pratique, il est préférable de transférer les
données en plusieurs parties d'au plus quelques méga-octets.
Pour modifier l'emplacement courant de lecture ou écriture associé au descripteur d'un objet large, on utilise
int lo_lseek(PGconn *conn, int fd, int offset, int whence);
Cette fonction déplace le pointeur
d'emplacement courant pour le descripteur de l'objet large identifié par
fd
au nouvel emplacement spécifié avec le décalage
(offset
). Les valeurs valides pour
whence
sont SEEK_SET
(rechercher depuis le début de l'objet), SEEK_CUR
(rechercher depuis la position courante) et SEEK_END
(rechercher depuis la fin de l'objet). Le code de retour est le nouvel
emplacement du pointeur ou -1 en cas d'erreur.
Lors de la gestion de Large Objects qui pourraient dépasser 2 Go, utilisez à la place
pg_int64 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence);
Cette fonction a le même comportement que lo_lseek
mais elle peut accepter un offset
supérieure à 2 Go
et/ou rendre un résultat supérieur à 2 Go. Notez que
lo_lseek
échouera si le nouveau pointeur
d'emplacement est supérieur à 2 Go.
lo_lseek64
apparaît avec
PostgreSQL
9.3. Si cette fonction est exécutée sur un serveur de version antérieure,
elle échouera et renverra -1.
Pour obtenir la position actuelle de lecture ou écriture d'un descripteur d'objet large, appelez
int lo_tell(PGconn *conn, int fd);
S'il n'y a pas d'erreur, la valeur renvoyée est -1.
Lors de la gestion de « Large Objects » qui pourraient dépasser 2 Go, utilisez à la place
pg_int64 lo_tell64(PGconn *conn, int fd);
Cette fonction a le même comportement que lo_tell
mais
elle peut gérer des objets de plus de 2 Go. Notez que lo_tell
échouera si l'emplacement de lecture/écrire va au-delà des 2 Go.
lo_tell64
est disponible depuis la version 9.3 de
PostgreSQL. Si cette fonction est utilisée sur
une ancienne version, elle échouera et renverra -1.
Pour tronquer un objet large avec une longueur donnée, on utilise
int lo_truncate(PGconn *conn, int fd, size_t len);
Cette fonction tronque le « Large Object » décrit par
fd
avec la longueur len
.
L'argument fd
doit avoir été renvoyé par un appel
précédent à lo_open
. Si la valeur du paramètre
len
est plus grand que la longueur actuelle du
« Large Object », ce dernier est étendu à la longueur spécifié avec des
octets nuls ('\0'). En cas de succès, lo_truncate
renvoit 0. En cas d'erreur, il renvoit -1.
L'emplacement de lecture/écriture associé avec le descripteur
fd
n'est pas modifié.
Bien que le paramètre len
est déclaré
size_t
, lo_truncate
rejettera toute
longueur supérieure à INT_MAX
.
Lors de la gestion de « Large Objects » qui pourraient dépasser 2 Go, utilisez à la place
int lo_truncate64(PGconn *conn, int fd, pg_int64 len);
Cette fonction a le même comportement que lo_truncate
mais elle peut accepter une valeur supérieure à 2 Go pour le paramètre
len
.
lo_truncate
est une nouveauté de PostgreSQL
8.3; si cette fonction est également exécuté sur un version plus ancienne du serveur,
elle échouera et retournera -1.
lo_truncate64
est disponible depuis la version 9.3 de
PostgreSQL. Si cette fonction est utilisée sur
une ancienne version, elle échouera et renverra -1.
Un descripteur d'objet large peut être fermé en appelant
int lo_close(PGconn *conn, int fd);
où fd
est un
descripteur d'objet large renvoyé par lo_open
. En
cas de succès, lo_close
renvoie zéro. -1 en cas d'échec.
Tous les descripteurs d'objets larges restant ouverts à la fin d'une transaction seront automatiquement fermés.