Обработка замечаний

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

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

Функция PQsetNoticeReceiver устанавливает или просматривает текущий приемник замечаний для объекта подключения. Аналогично функция PQsetNoticeProcessor устанавливает или просматривает текущий обработчик замечаний.

typedef void (*PQnoticeReceiver) (void *arg, const PGresult *res);

PQnoticeReceiver
PQsetNoticeReceiver(PGconn *conn,
                    PQnoticeReceiver proc,
                    void *arg);

typedef void (*PQnoticeProcessor) (void *arg, const char *message);

PQnoticeProcessor
PQsetNoticeProcessor(PGconn *conn,
                     PQnoticeProcessor proc,
                     void *arg);

Каждая из этих функций возвращает указатель на предыдущий приемник или обработчик замечаний и устанавливает для него новое значение. Если передать ей пустой указатель, ничего не происходит, но возвращается текущий указатель.

Когда сообщение с замечанием или предупреждением поступает от сервера или внутренне генерируется libpq, вызывается функция приемника замечаний. Сообщение передается ей в форме объекта PGresult со статусом PGRES_NONFATAL_ERROR. (Это позволяет приемнику извлечь из него отдельные поля с помощью функции PQresultErrorField или получить полное сообщение в заданном формате с помощью функции PQresultErrorMessage или PQresultVerboseErrorMessage.) Также ей передается тот же неопределенный указатель, что был передан функции PQsetNoticeReceiver. (При необходимости этот указатель можно использовать для обращения к внутреннему состоянию приложения.)

Стандартный приемник замечаний просто извлекает сообщение (с помощью функции PQresultErrorMessage) и передает его обработчику замечаний.

Обработчик замечаний отвечает за обработку сообщения с замечанием или предупреждением, заданным в текстовой форме. Ему передается строка с текстом сообщения (включающая завершающий символ перевода строки) плюс тот же неопределенный указатель, что был передан функции PQsetNoticeProcessor. (При необходимости этот указатель можно использовать для обращения к внутреннему состоянию приложения.)

Стандартный обработчик замечаний прост:

static void
defaultNoticeProcessor(void *arg, const char *message)
{
    fprintf(stderr, "%s", message);
}

После установки приемника или обработчика замечаний следует ожидать, что эта функция будет вызываться, пока будут существовать созданные с ней объект PGconn или объекты PGresult. При создании PGresult указатели текущих обработчиков замечаний, установленные в PGconn, копируются в PGresult для возможного использования функциями вроде PQgetvalue.