33.20. Сборка программ с libpq

Чтобы собрать (то есть, скомпилировать и скомпоновать) программу, использующую libpq, вы должны проделать следующие действия:

  • Включите заголовочный файл libpq-fe.h:

    #include <libpq-fe.h>

    Если вы не сделаете этого, обычно вас ждут примерно такие сообщения об ошибках от компилятора:

    foo.c: In function `main':
    foo.c:34: `PGconn' undeclared (first use in this function)
    foo.c:35: `PGresult' undeclared (first use in this function)
    foo.c:54: `CONNECTION_BAD' undeclared (first use in this function)
    foo.c:68: `PGRES_COMMAND_OK' undeclared (first use in this function)
    foo.c:95: `PGRES_TUPLES_OK' undeclared (first use in this function)
    
  • Сообщите вашему компилятору каталог, в котором установлены заголовочные файлы PostgreSQL, передав ему параметр -Iкаталог. (В некоторых случаях компилятор сам может обращаться к нужному каталогу, так что этот параметр можно опустить.) Например, ваша команда компиляции может быть такой:

    cc -c -I/usr/local/pgsql/include testprog.c

    Если вы используете скрипты сборки Makefile, добавьте этот параметр в переменную CPPFLAGS:

    CPPFLAGS += -I/usr/local/pgsql/include

    Если существует возможность, что вашу программу будут компилировать другие пользователи, то путь к каталогу не следует жёстко задавать таким образом. Вместо этого вы можете воспользоваться утилитой pg_config и узнать, где в локальной системе находятся заголовочные файлы, следующим образом:

    $ pg_config --includedir
    /usr/local/include
    

    Если у вас установлена программа pkg-config, вместо этого вы можете выполнить:

    $ pkg-config --cflags libpq
    -I/usr/local/include
    

    Заметьте, что при этом перед путём сразу будет добавлен ключ -I.

    Если требуемый параметр не будет передан компилятору, вы получите примерно такое сообщение об ошибке:

    testlibpq.c:8:22: libpq-fe.h: No such file or directory
    
  • При компоновке окончательной программы добавьте параметр -lpq, чтобы была подключена библиотека libpq, а также параметр -Lкаталог, указывающий на каталог, в котором находится libpq. (Опять же, компилятор будет просматривать определённые каталоги по умолчанию.) Для максимальной переносимости указывайте ключ -L перед параметром -lpq. Например:

    cc -o testprog testprog1.o testprog2.o -L/usr/local/pgsql/lib -lpq

    Каталог с библиотекой можно узнать, так же используя pg_config:

    $ pg_config --libdir
    /usr/local/pgsql/lib
    

    Или с помощью той же программы pkg-config:

    $ pkg-config --libs libpq
    -L/usr/local/pgsql/lib -lpq
    

    Заметьте, что и в этом случае выводится полностью сформированный параметр, а не только путь.

    В случае проблем в этой области возможны примерно такие сообщения об ошибках:

    testlibpq.o: In function `main':
    testlibpq.o(.text+0x60): undefined reference to `PQsetdbLogin'
    testlibpq.o(.text+0x71): undefined reference to `PQstatus'
    testlibpq.o(.text+0xa4): undefined reference to `PQerrorMessage'
    

    Они означают, что вы забыли добавить параметр -lpq.

    /usr/bin/ld: cannot find -lpq
    

    Такая ошибка означает, что вы забыли добавить ключ -L или не указали правильный каталог.

34.12. Large Objects

Large objects are not directly supported by ECPG, but ECPG application can manipulate large objects through the libpq large object functions, obtaining the necessary PGconn object by calling the ECPGget_PGconn() function. (However, use of the ECPGget_PGconn() function and touching PGconn objects directly should be done very carefully and ideally not mixed with other ECPG database access calls.)

For more details about the ECPGget_PGconn(), see Section 34.11. For information about the large object function interface, see Chapter 33.

Large object functions have to be called in a transaction block, so when autocommit is off, BEGIN commands have to be issued explicitly.

Example 34.2 shows an example program that illustrates how to create, write, and read a large object in an ECPG application.

Example 34.2. ECPG Program Accessing Large Objects

#include <stdio.h>
#include <stdlib.h>
#include <libpq-fe.h>
#include <libpq/libpq-fs.h>

EXEC SQL WHENEVER SQLERROR STOP;

int
main(void)
{
    PGconn     *conn;
    Oid         loid;
    int         fd;
    char        buf[256];
    int         buflen = 256;
    char        buf2[256];
    int         rc;

    memset(buf, 1, buflen);

    EXEC SQL CONNECT TO testdb AS con1;
    EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT;

    conn = ECPGget_PGconn("con1");
    printf("conn = %p\n", conn);

    /* create */
    loid = lo_create(conn, 0);
    if (loid &lt; 0)
        printf("lo_create() failed: %s", PQerrorMessage(conn));

    printf("loid = %d\n", loid);

    /* write test */
    fd = lo_open(conn, loid, INV_READ|INV_WRITE);
    if (fd &lt; 0)
        printf("lo_open() failed: %s", PQerrorMessage(conn));

    printf("fd = %d\n", fd);

    rc = lo_write(conn, fd, buf, buflen);
    if (rc &lt; 0)
        printf("lo_write() failed\n");

    rc = lo_close(conn, fd);
    if (rc &lt; 0)
        printf("lo_close() failed: %s", PQerrorMessage(conn));

    /* read test */
    fd = lo_open(conn, loid, INV_READ);
    if (fd &lt; 0)
        printf("lo_open() failed: %s", PQerrorMessage(conn));

    printf("fd = %d\n", fd);

    rc = lo_read(conn, fd, buf2, buflen);
    if (rc &lt; 0)
        printf("lo_read() failed\n");

    rc = lo_close(conn, fd);
    if (rc &lt; 0)
        printf("lo_close() failed: %s", PQerrorMessage(conn));

    /* check */
    rc = memcmp(buf, buf2, buflen);
    printf("memcmp() = %d\n", rc);

    /* cleanup */
    rc = lo_unlink(conn, loid);
    if (rc &lt; 0)
        printf("lo_unlink() failed: %s", PQerrorMessage(conn));

    EXEC SQL COMMIT;
    EXEC SQL DISCONNECT ALL;
    return 0;
}