Обработка замечаний
Сообщения с замечаниями и предупреждениями, генерируемые сервером, не возвращаются функциями, выполняющими запросы, поскольку они не подразумевают ошибку в запросе. Вместо этого они передаются функции обработки замечаний, и после завершения этого обработчика выполнение продолжается как обычно. Стандартная функция обработки замечаний выводит сообщение в 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.