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ée 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 ou -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,
    quelles que 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 renvoie 0. En cas d'erreur, il
    renvoie -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.