×
Мы обрабатываем cookies, чтобы сделать наш сайт удобнее и персонализированнее для вас. Подробнее: политика использования «cookies» и «политики конфиденциальности».

Для самостоятельной настройки ознакомьтесь с инструкцией

Дополнительные настройки cookies в браузерах

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

При отключении обработки cookie наш сайт продолжит функционировать, однако будут использоваться исключительно необходимые технические файлы, без которых работа ресурса невозможна.

Инструкция по отключению cookies
Принять
Настроить
Отклонить

ДОКУМЕНТАЦИЯ

Выберите версию, форк и язык для СУБД Digital Q.DataBase, чтобы прочитать или скачать всю документацию.
Техподдержка
Документация
Диасофт
Авторские права © 2016–2025 ООО "Диасофт Экосистема"
Скачать всю документацию:

4.1.22. Примеры программ

Данные и другие примеры программ находятся в директории src/test/examples в дистрибутиве исходного кода.

Пример 4.1.1. libpq Пример программы №1


/*
 * src/test/examples/testlibpq.c
 *
 *
 * testlibpq.c
 *
 *      Тестирование C-версии libpq, клиентской библиотеки PostgreSQL.
 */
#include 
#include 
#include "libpq-fe.h"

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

int
main(int argc, char **argv)
{
    const char *conninfo;
    PGconn     *conn;
    PGresult   *res;
    int         nFields;
    int         i,
                j;

    /*
     * Если пользователь передает параметр в командной строке, он используется в качестве
     * строки conninfo; в противном случае по умолчанию устанавливается значение dbname=postgres и используются
     * переменные окружения или значения по умолчанию для всех остальных параметров соединения.
     */
    if (argc > 1)
        conninfo = argv[1];
    else
        conninfo = "dbname = postgres";

    /* Установка соединения с базой данных */
    conn = PQconnectdb(conninfo);

    /* Проверка успешности установления соединения с серверной частью */
    if (PQstatus(conn) != CONNECTION_OK)
    {
        fprintf(stderr, "%s", PQerrorMessage(conn));
        exit_nicely(conn);
    }

    /* Установка безопасного пути поиска (search_path), чтобы исключить возможность захвата управления злоумышленниками. */
    res = PQexec(conn,
                 "SELECT pg_catalog.set_config('search_path', '', false)");
    if (PQresultStatus(res) != PGRES_TUPLES_OK)
    {
        fprintf(stderr, "Ошибка при выполнении SET: %s", PQerrorMessage(conn));
        PQclear(res);
        exit_nicely(conn);
    }

    /*
     * Для предотвращения утечек памяти необходимо вызывать функцию PQclear для типа PGresult,
     * как только объект перестает быть нужным.
     */
    PQclear(res);

    /*
     * Данный пример предполагает использование курсора, для которого выполнение должно происходить
     * внутри блока транзакции. Мы могли бы выполнить всю операцию с помощью одного вызова
     * функции PQexec() с запросом "select * from pg_database", однако это слишком тривиально
     * для наглядного примера.
     */

    /* Начало блока транзакции */
    res = PQexec(conn, "BEGIN");
    if (PQresultStatus(res) != PGRES_COMMAND_OK)
    {
        fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn));
        PQclear(res);
        exit_nicely(conn);
    }
    PQclear(res);

    /*
     * Извлечение строк из системного каталога баз данных pg_database
     */
    res = PQexec(conn, "DECLARE myportal CURSOR FOR select * from pg_database");
    if (PQresultStatus(res) != PGRES_COMMAND_OK)
    {
        fprintf(stderr, "DECLARE CURSOR failed: %s", PQerrorMessage(conn));
        PQclear(res);
        exit_nicely(conn);
    }
    PQclear(res);

    res = PQexec(conn, "FETCH ALL in myportal");
    if (PQresultStatus(res) != PGRES_TUPLES_OK)
    {
        fprintf(stderr, "FETCH ALL failed: %s", PQerrorMessage(conn));
        PQclear(res);
        exit_nicely(conn);
    }

    /* сначала вывод имен атрибутов */
    nFields = PQnfields(res);
    for (i = 0; i < nFields; i++)
        printf("%-15s", PQfname(res, i));
    printf("\n\n");

    /* далее выводятся строки */
    for (i = 0; i < PQntuples(res); i++)
    {
        for (j = 0; j < nFields; j++)
            printf("%-15s", PQgetvalue(res, i, j));
        printf("\n");
    }

    PQclear(res);

    /* закрытие портала... проверка на наличие ошибок не выполняется... */
    res = PQexec(conn, "CLOSE myportal");
    PQclear(res);

    /* завершение транзакции */
    res = PQexec(conn, "END");
    PQclear(res);

    /* закрытие соединения с базой данных и очистка ресурсов */
    PQfinish(conn);

    return 0;
}


Пример 4.1.2. libpq Пример программы 2


/*  * src/test/examples/testlibpq2.c  *  *  * testlibpq2.c  *      Тестирование интерфейса асинхронных уведомлений  *  * Запустите эту программу, затем в другом окне psql выполните  *   NOTIFY TBL2;  * Повторите четыре раза для завершения работы программы.  *  * При необходимости можно использовать следующий вариант:  * заполните базу данных с помощью следующих команд  * (представлены в файле src/test/examples/testlibpq2.sql):  *  *   CREATE SCHEMA TESTLIBPQ2;  *   SET search_path = TESTLIBPQ2;  *   CREATE TABLE TBL1 (i int4);  *   CREATE TABLE TBL2 (i int4);  *   CREATE RULE r1 AS ON INSERT TO TBL1 DO  *     (INSERT INTO TBL2 VALUES (new.i); NOTIFY TBL2);  *  * Запустите эту программу, затем в psql выполните следующее действие четыре раза:  *  *   INSERT INTO TESTLIBPQ2.TBL1 VALUES (10);  */  #ifdef WIN32 #include  #endif #include  #include  #include  #include  #include  #include  #include   #include "libpq-fe.h"  static void exit_nicely(PGconn *conn) {
    PQfinish(conn);
    exit(1);
}

int
main(int argc, char **argv)
{
    const char *conninfo;
    PGconn     *conn;
    PGresult   *res;
    PGnotify   *notify;
    int         nnotifies;      /*      * Если пользователь передает параметр в командной строке, он используется в качестве      * строки conninfo; в противном случае по умолчанию устанавливается значение dbname=postgres и используются
     * переменные окружения или значения по умолчанию для всех остальных параметров соединения.
     */
    if (argc > 1)
        conninfo = argv[1];
    else
        conninfo = "dbname = postgres";

    /* Установка соединения с базой данных */
    conn = PQconnectdb(conninfo);

    /* Проверка успешности установления соединения с серверной частью */
    if (PQstatus(conn) != CONNECTION_OK)
    {
        fprintf(stderr, "%s", PQerrorMessage(conn));
        exit_nicely(conn);
    }

    /* Установка безопасного пути поиска (search_path), чтобы исключить возможность захвата управления злоумышленниками. */
    res = PQexec(conn,
                 "SELECT pg_catalog.set_config('search_path', '', false)");
    if (PQresultStatus(res) != PGRES_TUPLES_OK)
    {
        fprintf(stderr, "Ошибка при выполнении SET: %s", PQerrorMessage(conn));
        PQclear(res);
        exit_nicely(conn);     }      /*      * Чтобы избежать утечек памяти, следует вызывать функцию PQclear для типа PGresult      * каждый раз, когда он больше не требуется      */     PQclear(res);      /*      * Для включения уведомлений от команды NOTIFY выполните команду LISTEN.      */     res = PQexec(conn, "LISTEN TBL2");     if (PQresultStatus(res) != PGRES_COMMAND_OK)     {
        fprintf(stderr, "Команда LISTEN не выполнена: %s", PQerrorMessage(conn));
        PQclear(res);
        exit_nicely(conn);
    }
    PQclear(res);

    /* Завершение работы после получения четырех уведомлений. */
    nnotifies = 0;
    while (nnotifies < 4)
    {
        /*
         * Ожидание события в соединении. Для ожидания ввода используется системный вызов select(2),
         * однако также можно использовать функцию poll() или аналогичные
         * средства.
         */
        int         sock;
        fd_set      input_mask;

        sock = PQsocket(conn);

        if (sock < 0)
            break;              /* этого не должно происходить */

        FD_ZERO(&input_mask);
        FD_SET(sock, &input_mask);

        if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0)
        {
            fprintf(stderr, "вызов select() завершился ошибкой: %s\n", strerror(errno));
            exit_nicely(conn);
        }

        /* Проверка наличия входных данных */
        PQconsumeInput(conn);
        while ((notify = PQnotifies(conn)) != NULL)
        {
            fprintf(stderr,
                    "Получено уведомление ASYNC NOTIFY «%s» от серверного процесса с PID %d\n",
                    notify->relname, notify->be_pid);
            PQfreemem(notify);
            nnotifies++;
            PQconsumeInput(conn);
        }
    }

    fprintf(stderr, "Завершено.\n");

    /* закрытие соединения с базой данных и очистка ресурсов */
    PQfinish(conn);

    return 0;
}


Пример 4.1.3. libpq Пример программы № 3


/*
 * src/test/examples/testlibpq3.c
 *
 *
 * testlibpq3.c
 *      Тестирование внешних параметров и двоичного ввода-вывода.
 *
 * Перед запуском заполните базу данных с помощью следующих команд
 * (содержатся в файле src/test/examples/testlibpq3.sql):
 *
 * CREATE SCHEMA testlibpq3;
 * SET search_path = testlibpq3;
 * SET standard_conforming_strings = ON;
 * CREATE TABLE test1 (i int4, t text, b bytea);
 * INSERT INTO test1 values (1, 'joe''s place', '\000\001\002\003\004');
 * INSERT INTO test1 values (2, 'ho there', '\004\003\002\001\000');
 *
 * Ожидаемый результат:
 *
 * кортеж 0: получено
 *  i = (4 байта) 1
 *  t = (11 байт) 'joe's place'
 *  b = (5 байт) \000\001\002\003\004
 *
 * кортеж 0: получено
 *  i = (4 байта) 2
 *  t = (8 байт) 'ho there'
 *  b = (5 байт) \004\003\002\001\000
 */

#ifdef WIN32
#include 
#endif

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

/* для ntohl/htonl */
#include 
#include 


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

/*
 * Данная функция выводит результат запроса, полученный в двоичном формате
 * из таблицы, определение которой приведено в комментарии выше.  Мы выделили её отдельно, так как
 * функция main() использует её дважды.
 */
static void
show_binary_results(PGresult *res)
{
    int         i,
                j;
    int         i_fnum,
                t_fnum,
                b_fnum;

    /* Использование функции PQfnumber позволяет избежать предположений о порядке полей в результате */
    i_fnum = PQfnumber(res, "i");
    t_fnum = PQfnumber(res, "t");
    b_fnum = PQfnumber(res, "b");

    for (i = 0; i < PQntuples(res); i++)
    {
        char       *iptr;
        char       *tptr;
        char       *bptr;
        int         blen;
        int         ival;

        /* Получение значений полей (возможность наличия в них значения NULL игнорируется!) */
        iptr = PQgetvalue(res, i, i_fnum);
        tptr = PQgetvalue(res, i, t_fnum);
        bptr = PQgetvalue(res, i, b_fnum);

        /*
         * Бинарное представление типа INT4 использует сетевой порядок байтов, который
         * целесообразно преобразовать в локальный порядок байтов.
         */
        ival = ntohl(*((uint32_t *) iptr));

        /*
         * Бинарное представление типа TEXT представляет собой текст, и поскольку библиотека libpq
         * автоматически добавляет к нему нулевой байт, он будет корректно обрабатываться
         * в качестве строки языка C.
         *
         * Бинарное представление типа BYTEA является набором байтов, который может
         * содержать встроенные значения NULL, поэтому необходимо учитывать длину поля.
         */
        blen = PQgetlength(res, i, b_fnum);

        printf("tuple %d: got\n", i);
        printf(" i = (%d bytes) %d\n",
               PQgetlength(res, i, i_fnum), ival);
        printf(" t = (%d bytes) '%s'\n",
               PQgetlength(res, i, t_fnum), tptr);
        printf(" b = (%d bytes) ", blen);
        for (j = 0; j < blen; j++)
            printf("\\%03o", bptr[j]);
        printf("\n\n");
    }
}

int
main(int argc, char **argv)
{
    const char *conninfo;
    PGconn     *conn;
    PGresult   *res;
    const char *paramValues[1];
    int         paramLengths[1];
    int         paramFormats[1];
    uint32_t    binaryIntVal;

    /*
     * Если пользователь передает параметр в командной строке, он используется в качестве
     * строки conninfo; в противном случае по умолчанию устанавливается значение dbname=postgres и используются
     * переменные окружения или значения по умолчанию для всех остальных параметров соединения.
     */
    if (argc > 1)
        conninfo = argv[1];
    else
        conninfo = "dbname = postgres";

    /* Установка соединения с базой данных */
    conn = PQconnectdb(conninfo);

    /* Проверка успешности установления соединения с серверной частью */
    if (PQstatus(conn) != CONNECTION_OK)
    {
        fprintf(stderr, "%s", PQerrorMessage(conn));
        exit_nicely(conn);
    }

    /* Для предотвращения захвата управления злоумышленниками устанавливается безопасный путь поиска. */
    res = PQexec(conn, "SET search_path = testlibpq3");
    if (PQresultStatus(res) != PGRES_COMMAND_OK)
    {
        fprintf(stderr, "Ошибка при выполнении SET: %s", PQerrorMessage(conn));
        PQclear(res);
        exit_nicely(объект conn);
    }
    PQclear(res);

    /*
     * Цель данной программы заключается в демонстрации использования функции PQexecParams()
     * с внешними параметрами, а также передачи данных в бинарном формате.
     *
     * В этом первом примере параметры передаются в виде текста, но результаты
     * принимаются в бинарном формате. Используя внешние параметры, можно избежать
     * кропотливой работы с кавычками и экранированием, даже если
     * данные являются текстовыми. Обратите внимание, что нам не нужно выполнять никаких специальных
     * действий с символом кавычки в значении параметра.
     */

    /* Ниже приведено значение нашего внешнего параметра */
    paramValues[0] = "joe's place";

    res = PQexecParams(объект conn,
                       "SELECT * FROM test1 WHERE t = $1",
                       1,       /* один параметр */
                       значение NULL,    /* позволить бэкенду определить тип параметра */
                       paramValues,
                       значение NULL,    /* длины параметров не требуются, так как используется текстовый формат */
                       значение NULL,    /* по умолчанию все параметры являются текстовыми */
                       1);      /* запрос результатов в бинарном формате */

    if (PQresultStatus(res) != PGRES_TUPLES_OK)
    {
        fprintf(stderr, "Ошибка SELECT: %s", PQerrorMessage(объект conn));
        PQclear(res);
        exit_nicely(объект conn);
    }

    show_binary_results(res);

    PQclear(res);

    /*
     * Во втором примере целочисленный параметр передается в бинарном формате,
     * и результаты снова извлекаются в бинарном формате.
     *
     * Хотя функции PQexecParams передается указание позволить серверной части определить
     * тип параметра, фактически выбор навязывается путем приведения типа символа
     * параметра в тексте запроса. Это является надежной мерой безопасности при передаче
     * бинарных параметров.
     */

    /* Преобразование целочисленного значения «2» в сетевой порядок байтов */
    binaryIntVal = htonl((uint32_t) 2);

    /* Подготовка массивов параметров для функции PQexecParams */
    paramValues[0] = (char *) &binaryIntVal;
    paramLengths[0] = sizeof(binaryIntVal);
    paramFormats[0] = 1;        /* двоичный формат */

    res = PQexecParams(conn,
                       "SELECT * FROM test1 WHERE i = $1::int4",
                       1,       /* один параметр */
                       значение NULL,    /* позволить бэкенду определить тип параметра */
                       paramValues,
                       paramLengths,
                       paramFormats,
                       1);      /* запрос результатов в бинарном формате */

    if (PQresultStatus(res) != PGRES_TUPLES_OK)
    {
        fprintf(stderr, "Ошибка SELECT: %s", PQerrorMessage(объект conn));
        PQclear(res);
        exit_nicely(conn);
    }

    show_binary_results(res);

    PQclear(res);

    /* закрытие соединения с базой данных и очистка ресурсов */
    PQfinish(conn);

    return 0;
}


Наверх
свяжитесь
с нами
контакты
Для прямой связи с нами вы можете использовать контакты ниже, либо оставить заявку через форму обратной связи, и мы обязательно свяжемся с вами

*поля обязательные к заполнению