2012-03-23 5 views
1

Я добавляю обработку исключений в хранимые процедуры PostgreSQL для автоматического отката транзакций после возникновения ошибки.Возврат данных об ошибках вызывающей функции после обнаружения исключения в Postgresql

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

Серьезность, SQLSTATE, Первичный, Подробный и Подсказка - все значения null. Есть ли способ вернуть их после обнаружения исключения?

Функция libpq, которую я использую для сбора этих значений, - PQresultErrorField().

ответ

1

Я недавно разместил complete solution how to add a CONTEXT to error messages on dba.SE. Трюк состоит в том, чтобы вызвать функцию, которая вызывает ошибку/предупреждение/уведомление/и т. Д.

Теперь я понимаю, что ваш случай может быть другим. Мое обходное решение заключается в добавлении КОНТЕКСТ к исключениям, которые вы поднимаете сами.

Если вы ловите исключение делать вещи, прежде чем транзакция откатывается назад, вы можете добавить RAISE без параметров в конце вашего блока исключения:

RAISE; 

manual about RAISE:

The last variant of RAISE has no parameters at all. This form can only be used inside a BEGIN block's EXCEPTION clause; it causes the error currently being handled to be re-thrown.

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

2

Предоставлено исключение автоматически сделает вскрытие транзакции postgresql, зачем вообще ее вообще ловить? Захват исключений обычно полезен только в том случае, если вы хотите извлечь полезную пользу из этой ошибки, а не распространять ее.

+0

Точно. Возможно, у ОП есть какое-то приложение с более чем одним соединением, требующее двухфазной фиксации? – wildplasser

+0

Не могли бы вы рассказать об этом? Я принимал то же самое, однако, когда я вызываю процедуру, которая возвращает курсор, который я хочу перебрать, и в какой-то момент я вызываю исключение, это то, что я получаю: «ОШИБКА: текущая транзакция прерывается, команды игнорируются до конца транзакционный блок ". Поэтому из того, что я понимаю, я должен поймать исключение в моей процедуре, чтобы откат. Я ошибаюсь? –

+0

Хорошая точка. Все откидывается назад, бесполезно пытаться что-то убрать. Однако есть редкие исключения, такие как эффекты вызовов dblink, которые никогда не откатываются назад. То, что OP понадобится в таком случае, - это вызвать «RAISE;» в конце блока исключения, я соответствующим образом изменил свой ответ. –