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 Unix avec des
analogies pour les fonctions 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. Les opérations d'écriture, incluant
lo_open
avec le mode INV_WRITE
, ne
sont pas autorisées dans une transaction en lecture seule.
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 se lier à la
bibliothèque libpq.
Les applications clientes ne peuvent pas utiliser ces fonctions quand une connexion libpq est en mode pipeline.
Oid lo_create(PGconn *conn, Oid lobjId);
crée un nouveau « Large Object ». L'OID affecté peut être indiqué
par le paramètre lobjId
;
dans ce cas, un échec survient si l'OID est déjà utilisé par un autre Large
Object. Si lobjId
vaut
InvalidOid
(zéro), alors lo_create
affecte un OID inutilisé. La valeur de retour est l'OID assigné au nouveau
« Large Object » ou InvalidOid
(zéro) en cas
d'erreur.
Un exemple :
inv_oid = lo_create(conn, oid_désiré);
Oid lo_creat(PGconn *conn, int mode);
crée aussi un nouveau « Large Object », toujours
affecté à un OID inutilisé. La valeur de retour est l'OID qui a été affecté
au nouveau « Large Object » ou InvalidOid
(zéro)
en cas d'échec.
Dans les versions 8.1 et ultérieures de
PostgreSQL, le mode
est ignoré, pour que
lo_creat
soit exactement équivalent à
lo_create
avec un deuxième argument à zéro. Néanmoins,
il y a peu de raisons d'utiliser lo_creat
sauf si vous
avez besoin d'utiliser des serveurs antérieurs à la version 8.1. Pour
travailler avec des serveurs si vieux, vous devez utiliser
lo_creat
, et non pas lo_create
, et
vous devez configurer mode
à
une valeur parmi INV_READ
, INV_WRITE
et
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);
Pour importer un fichier du système d'exploitation en tant que « Large Object », appelez
Oid lo_import(PGconn *conn, const char *filename);
filename
spécifie le nom du
fichier à importer comme « Large Object ». Le code de retour
est l'OID assigné au nouveau « Large Object » ou
InvalidOid
(zéro) 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 être lisible
par l'application du client.
Oid lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId);
importe aussi un nouveau « 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 apparu avec
PostgreSQL 8.4, et utilise en interne
lo_create
qui était une nouveauté de la version
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 « Large Object » 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 du « Large
Object » à 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 « Large Object » existant pour lire ou écrire, appelez
int lo_open(PGconn *conn, Oid lobjId, int mode);
L'argument lobjId
spécifie l'OID du « Large
Object » à ouvrir. Les bits mode
contrôlent
si le « Large Object » est ouvert en lecture
(INV_READ
), en é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) de « Large Object » 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 du « Large Object » 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
provenir d'un appel précédent à la fonction lo_open
.
Le nombre d'octets réellement écrits 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é fourni par un appel précédent à
la fonction 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 « Large Object », 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 du « Large Object » 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 de « Large Object », 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 « Large Object » 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 grande que la longueur actuelle du
« Large Object », ce dernier est étendu à la longueur spécifiée
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 de « Large Object » peut être fermé en appelant
int lo_close(PGconn *conn, int fd);
où fd
est un descripteur de « Large
Object » renvoyé par lo_open
. En cas de succès,
lo_close
renvoie zéro. -1 en cas d'échec.
Tous les descripteurs de « Large Objects » restant ouverts à la fin d'une transaction seront automatiquement fermés.
Pour supprimer un « Large Object » de la base de données, on utilise
int lo_unlink(PGconn *conn, Oid lobjId);
L'argument lobjId
spécifie l'OID du « Large
Object » à supprimer. En cas d'erreur, le code de retour est -1.