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 - это глобальная переменная).