Перейти к основному содержимому

Обработка ошибок в PL/Tcl

примечание

Эта страница переведена при помощи нейросети GigaChat.

Код Tcl внутри функции PL/Tcl или вызываемый из нее может вызвать ошибку, выполнив некорректную операцию или сгенерировав ошибку с помощью команды Tcl error или команды PL/Tcl elog. Такие ошибки могут быть перехвачены в 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.

Удобный способ работы с информацией PL/Tcl errorCode - загрузить ее в массив, чтобы имена полей стали индексами массива. Код для этого мог бы выглядеть так:

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