41.8. Обработка ошибок в PL/Tcl#
41.8. Обработка ошибок в PL/Tcl #
Код Tcl внутри или вызываемый из функции PL/Tcl может вызывать ошибку, либо выполняя некорректную операцию, либо генерируя ошибку с помощью команды Tcl error
или команды elog
PL/Tcl. Такие ошибки могут быть перехвачены в Tcl с помощью команды catch
. Если ошибка не перехватывается, но разрешается распространяться до верхнего уровня выполнения функции PL/Tcl, она сообщается как SQL-ошибка в вызывающем запросе функции.
В то же время, ошибки SQL, которые возникают внутри команд PL/Tcl spi_exec
, spi_prepare
и spi_execp
, сообщаются как ошибки Tcl, поэтому их можно перехватить с помощью команды Tcl catch
. (Каждая из этих команд PL/Tcl выполняет свою операцию SQL в подтранзакции, которая откатывается при ошибке, так что любая частично завершенная операция автоматически очищается). Опять же, если ошибка распространяется до верхнего уровня без перехвата, она превращается в ошибку SQL.
Tcl предоставляет переменную errorCode
, которая может представлять
дополнительную информацию об ошибке в формате, который легко интерпретировать
Tcl программам. Содержимое представлено в формате списка Tcl, и
первое слово идентифицирует подсистему или библиотеку, сообщающую об ошибке;
после этого содержимое остается на усмотрение отдельной подсистемы или
библиотеки. Для ошибок базы данных, сообщаемых командами PL/Tcl, первое
слово - POSTGRES
, второе слово - номер версии PostgreSQL,
а дополнительные слова - пары имя поля/значение, предоставляющие подробную информацию об ошибке.
Всегда предоставляются поля SQLSTATE
, condition
и
message
(первые два представляют код ошибки и имя состояния, как показано
в Предметный указатель A).
Поля, которые могут присутствовать, включают
detail
, hint
, context
,
schema
, table
, column
,
datatype
, constraint
,
statement
, cursor_position
,
filename
, lineno
и
funcname
.
Удобный способ работы с информацией errorCode
в PL/Tcl - загрузить ее в массив, чтобы имена полей стали подсценариями массива. Код для этого может выглядеть так
if {[catch { spi_exec $sql_command }]} { if {[lindex $::errorCode 0] == "POSTGRES"} { array set errorArray $::errorCode if {$errorArray(condition) == "undefined_table"} { # deal with missing table } else { # deal with some other type of SQL error } } }
(Двойные двоеточия явно указывают, что errorCode
- это глобальная переменная).