Documentation PostgreSQL 14.22 » Interfaces client » Large Objects » Interfaces client

Précédent | Niveau supérieur | Suivant
35.2. Fonctionnalités de l'implantation | Sommaire | 35.4. Fonctions du côté serveur

## 35.3. Interfaces client

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.

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.

### 35.3.1. Créer un « Large Object »

La fonction

    Oid lo_creat(PGconn *conn, int mode);

crée un nouveau « Large Object ». La valeur de retour est l'OID assigné au nouveau « Large Object » ou `InvalidOid` (zéro) en cas d'erreur. L'argument `mode` est inutilisé et ignoré depuis 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);

La fonction

    Oid lo_create(PGconn *conn, Oid lobjId);

crée aussi un nouveau « Large Object ». L'OID à affecter peut être spécifié avec l'argument `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_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 nouveau « Large Object » ou `InvalidOid`(zéro) en cas d'échec.

`lo_create` est apparu avec 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);

### 35.3.2. Importer un « Large Object »

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.

La fonction

    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`.

### 35.3.3. Exporter un « Large Object »

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.

### 35.3.4. Ouvrir un « Large Object » existant

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);

### 35.3.5. Écrire des données dans un « Large Object »

La fonction

    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.

### 35.3.6. Lire des données à partir d'un « Large Object »

La fonction

    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.

### 35.3.7. Recherche dans un « Large Object »

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.

### 35.3.8. Obtenir la position de recherche d'un « Large Object »

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.

### 35.3.9. Tronquer un « Large Object »

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.

### 35.3.10. Fermer un descripteur de « Large Object »

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.

### 35.3.11. Supprimer un objet large

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.