30.12. Обработка замечаний
Сообщения с замечаниями и предупреждениями, выдаваемые сервером, не возвращаются функциями, выполняющими запросы, так как они не свидетельствуют об ошибке в запросе. Вместо этого они передаются функции обработки замечаний и после завершения этой функции выполнение продолжается как обычно. Стандартная функция обработки замечаний выводит сообщение в 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, вызывается функция приёмника замечания. Сообщение передаётся ей в виде состояния PGRES_NONFATAL_ERROR
объекта PGresult
. (Это позволяет приёмнику извлечь из него отдельные поля, используя PQresultErrorField
, либо получить полное готовое сообщение, вызвав PQresultErrorMessage
или PQresultVerboseErrorMessage
.) Ей также передаётся тот же неопределённый указатель, что был передан функции PQsetNoticeReceiver
. (Этот указатель может пригодиться для обращения к внутреннему состоянию приложения при необходимости.)
Стандартный приёмник замечаний просто извлекает сообщение (вызывая PQresultErrorMessage
) и передаёт его обработчику замечаний.
Обработчик замечаний отвечает за обработку сообщения с замечанием или предупреждением в текстовом виде. Ему передаётся строка с текстом сообщения (включающая завершающий символ новой строки) и неопределённый указатель, который был передан функции PQsetNoticeProcessor
. (Этот указатель может пригодиться для обращения к внутреннему состоянию приложения при необходимости.)
Стандартный обработчик замечаний прост:
static void defaultNoticeProcessor(void *arg, const char *message) { fprintf(stderr, "%s", message); }
Установив приёмник или обработчик замечаний, вы можете ожидать, что эта функция будет вызываться, пока будут существовать объект PGconn
или объекты PGresult
, созданные с ней. Когда создаётся PGresult
, указатели текущих обработчиков замечаний, установленные в PGconn
, копируются в PGresult
для возможного использования функциями вроде PQgetvalue
.