Код Tcl внутри функции PL/Tcl или вызываемый из неё может вызвать ошибку
либо в результате выполнения недопустимой операции, либо путём генерации ошибки
с помощью команды Tcl error или команды
PL/Tcl elog command. Такие ошибки могут быть перехвачены
внутри Tcl с помощью команды catch command. Если ошибка не была перехвачена и вышла на верхний уровень выполнения функции PL/Tcl, она регистрируется как ошибка SQL в запросе, вызвавшем эту функцию.
И наоборот, ошибки SQL, возникающие внутри команд PL/Tcl
spi_exec, spi_prepare,
и spi_execp передаются как ошибки Tcl,
поэтому их можно перехватить стандартной командой catch .
(Каждая из этих команд PL/Tcl выполняет соответствующую SQL-операцию в
подтранзакции, которая откатывается в случае ошибки, что обеспечивает автоматическую очистку
результатов частично выполненных действий.)
Если такая ошибка достигает верхнего уровня, не будучи перехваченной,
она снова преобразуется в ошибку SQL.
Tcl предоставляет errorCode переменную, которая может содержать дополнительную информацию об ошибке в удобном для интерпретации программами на Tcl виде. Содержимое представлено в формате списка Tcl, при этом первое слово идентифицирует подсистему или библиотеку, сообщившую об ошибке; структура остальной части данных определяется соответствующей подсистемой или библиотекой. Для ошибок базы данных, возвращаемых командами PL/Tcl, первым словом является POSTGRES, вторым словом — номер версии PostgreSQL, а последующими — пары «имя поля/значение», предоставляющие подробную информацию об ошибке. Поля SQLSTATE, condition,
и message предоставляются всегда
(первые два представляют собой код ошибки и имя условия, как показано
в Приложение 8.1).
К числу полей, которые могут присутствовать, относятся
detail, hint, context,
schema, table, column,
тип данных, ограничение,
оператор, cursor_position,
имя файла, номер строки, и
имя_функции.
Удобный способ работы с информацией в PL/Tcl errorCode
заключается в её загрузке в массив, при которой имена полей становятся индексами массива. Код для реализации этой задачи может выглядеть следующим образом:
if {[catch { spi_exec $sql_command }]} {
if {[lindex $::errorCode 0] == "POSTGRES"} {
array set errorArray $::errorCode
if {$errorArray(condition) == "undefined_table"} {
# обработка случая отсутствия таблицы
} else {
# обработка других типов ошибок SQL
}
}
}
(Двойное двоеточие явно указывает на то, что errorCode
является глобальной переменной.)