Documentation PostgreSQL 14.22 » Interfaces client » Large Objects » Programme d'exemple

Précédent | Niveau supérieur | Suivant
35.4. Fonctions du côté serveur | Sommaire | Chapitre 36. ECPG -- SQL embarqué en C

## 35.5. Programme d'exemple

L'Exemple 35.1 est un programme d'exemple qui montre une utilisation de l'interface des « Large Objects » avec la bibliothèque libpq. Des parties de ce programme disposent de commentaires au bénéfice des utilisateurs. Ce programme est aussi disponible dans la distribution des sources (`src/test/examples/testlo.c`).

Exemple 35.1. Exemple de programme sur les « Large Objects » avec libpq

    /*-------------------------------------------------------------------------
     *
     * testlo.c
     *    test utilisant des Large Objects avec libpq
     *
     * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
     * Portions Copyright (c) 1994, Regents of the University of California
     *
     *
     * IDENTIFICATION
     *    src/test/examples/testlo.c
     *
     *-------------------------------------------------------------------------
     */
    #include <stdlib.h>

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>

    #include "libpq-fe.h"
    #include "libpq/libpq-fs.h"

    #define BUFSIZE         1024

    /*
     * importFile -
     *    importe le fichier "in_filename" dans la base de données
     *    en tant qu'objet "lobjOid"
     *
     */
    static Oid
    importFile(PGconn *conn, char *filename)
    {
        Oid         lobjId;
        int         lobj_fd;
        char        buf[BUFSIZE];
        int         nbytes,
                    tmp;
        int         fd;

        /*
         * ouvre le fichier à lire
         */
        fd = open(filename, O_RDONLY, 0666);
        if (fd < 0)
        {                           /* error */
            fprintf(stderr, "cannot open unix file\"%s\"\n", filename);
        }

        /*
         * crée le Large Object
         */
        lobjId = lo_creat(conn, INV_READ | INV_WRITE);
        if (lobjId == 0)
            fprintf(stderr, "cannot create large object");

        lobj_fd = lo_open(conn, lobjId, INV_WRITE);

        /*
         * lit le fichier Unix écrit dans le fichier inversion
         */
        while ((nbytes = read(fd, buf, BUFSIZE)) > 0)
        {
            tmp = lo_write(conn, lobj_fd, buf, nbytes);
            if (tmp < nbytes)
                fprintf(stderr, "error while reading \"%s\"", filename);
        }

        close(fd);
        lo_close(conn, lobj_fd);

        return lobjId;
    }

    static void
    pickout(PGconn *conn, Oid lobjId, int start, int len)
    {
        int         lobj_fd;
        char       *buf;
        int         nbytes;
        int         nread;

        lobj_fd = lo_open(conn, lobjId, INV_READ);
        if (lobj_fd < 0)
            fprintf(stderr, "cannot open large object %u", lobjId);

        lo_lseek(conn, lobj_fd, start, SEEK_SET);
        buf = malloc(len + 1);

        nread = 0;
        while (len - nread > 0)
        {
            nbytes = lo_read(conn, lobj_fd, buf, len - nread);
            buf[nbytes] = '\0';
            fprintf(stderr, ">>> %s";, buf);
            nread += nbytes;
            if (nbytes <= 0)
                break;              /* no more data? */
        }
        free(buf);
        fprintf(stderr, "\n");
        lo_close(conn, lobj_fd);
    }

    static void
    overwrite(PGconn *conn, Oid lobjId, int start, int len)
    {
        int         lobj_fd;
        char       *buf;
        int         nbytes;
        int         nwritten;
        int         i;

        lobj_fd = lo_open(conn, lobjId, INV_WRITE);
        if (lobj_fd < 0)
            fprintf(stderr, "cannot open large object %u", lobjId);

        lo_lseek(conn, lobj_fd, start, SEEK_SET);
        buf = malloc(len + 1);

        for (i = 0; i < len; i++)
            buf[i] = 'X';
        buf[i] = '\0';

        nwritten = 0;
        while (len - nwritten > 0)
        {
            nbytes = lo_write(conn, lobj_fd, buf + nwritten, len - nwritten);
            nwritten += nbytes;
            if (nbytes <= 0)
            {
                fprintf(stderr, "\nWRITE FAILED!\n");
                break;
            }
        }
        free(buf);
        fprintf(stderr, "\n");
        lo_close(conn, lobj_fd);
    }

    /*
     * exportFile -
     *    exporte le Large Object "lobjOid" dans le fichier
     * "out_filename"
     *
     */
    static void
    exportFile(PGconn *conn, Oid lobjId, char *filename)
    {
        int         lobj_fd;
        char        buf[BUFSIZE];
        int         nbytes,
                    tmp;
        int         fd;

        /*
         * ouvre l' « objet » large
         */
        lobj_fd = lo_open(conn, lobjId, INV_READ);
        if (lobj_fd < 0)
            fprintf(stderr, "cannot open large object %u", lobjId);

        /*
         * ouvre le fichier à écrire
         */
        fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
        if (fd < 0)
        {                           /* error */
            fprintf(stderr, "cannot open unix file\"%s\"",
                    filename);
        }

        /*
         * lit à partir du fichier inversion et écrit dans le fichier Unix
         */
        while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE)) > 0)
        {
            tmp = write(fd, buf, nbytes);
            if (tmp < nbytes)
            {
                fprintf(stderr, "error while writing \"%s\"",
                        filename);
            }
        }

        lo_close(conn, lobj_fd);
        close(fd);
    }

    void
    exit_nicely(PGconn *conn)
    {
        PQfinish(conn);
        exit(1);
    }

    int
    main(int argc, char **argv)
    {
        char       *in_filename,
                   *out_filename;
        char       *database;
        Oid         lobjOid;
        PGconn     *conn;
        PGresult   *res;

        if (argc != 4)
        {
            fprintf(stderr, "Usage: %s database_name in_filename out_filename\n",
                    argv[0]);
            exit(1);
        }

        database = argv[1];
        in_filename = argv[2];
        out_filename = argv[3];

        /*
         * initialise la connexion
         */
        conn = PQsetdb(NULL, NULL, NULL, NULL, database);

        /* check to see that the backend connection was successfully made */
        if (PQstatus(conn) != CONNECTION_OK)
        {
            fprintf(stderr, "%s", PQerrorMessage(conn));
            exit_nicely(conn);
        }

        /* configure un chemin de recherche toujours sécurisé
         * pour que les utilisateurs avec de mauvaises intentions
         * ne puissent en prendre le contrôle.
         */
        res = PQexec(conn,
                     "SELECT pg_catalog.set_config('search_path', '', false)");
        if (PQresultStatus(res) != PGRES_TUPLES_OK)
        {
            fprintf(stderr, "SET failed: %s", PQerrorMessage(conn));
            PQclear(res);
            exit_nicely(conn);
        }
        PQclear(res);

        res = PQexec(conn, "begin");
        PQclear(res);
        printf("importing file \"%s\" ...\n", in_filename);
    /*  lobjOid = importFile(conn, in_filename); */
        lobjOid = lo_import(conn, in_filename);
        if (lobjOid == 0)
            fprintf(stderr, "%s\n", PQerrorMessage(conn));
        else
        {
            printf("\tas large object %u.\n", lobjOid);

            printf("picking out bytes 1000-2000 of the large object\n");
            pickout(conn, lobjOid, 1000, 1000);

            printf("overwriting bytes 1000-2000 of the large object with X's\n");
            overwrite(conn, lobjOid, 1000, 1000);

            printf("exporting large object to file \"%s\" ...\n", out_filename);
    /*      exportFile(conn, lobjOid, out_filename); */
            if (lo_export(conn, lobjOid, out_filename) < 0)
                fprintf(stderr, "%s\n", PQerrorMessage(conn));
        }

        res = PQexec(conn, "end");
        PQclear(res);
        PQfinish(conn);
        return 0;
    }