O código Tcl no corpo ou chamado por uma
função PL/Tcl pode gerar um erro, seja
executando alguma operação inválida, ou gerando um erro usando
o comando error do Tcl,
ou o comando elog do PL/Tcl.
Estes erros podem ser capturados no Tcl usando
o comando catch.
Se o erro não for capturado, e puder se propagar para o nível
superior de execução da função PL/Tcl, ele
será relatado como um erro de SQL na consulta
de chamada da função.
Diferentemente, erros de SQL que ocorrem nos
comandos spi_exec,
spi_prepare e spi_execp
do PL/Tcl são relatados como erros de
Tcl, portanto podem ser capturados pelo comando
catch do Tcl.
(Cada um desses comandos PL/Tcl executa sua
operação SQL em uma subtransação, desfeita
em caso de erro, para que qualquer operação parcialmente concluída
seja automaticamente limpa.)
Novamente, se o erro se propagar para o nível superior sem ser
capturado, voltará a ser um erro de SQL.
O Tcl fornece a variável
errorCode que pode representar informações
adicionais sobre o erro em um formato fácil de ser interpretado
pelos programas Tcl.
O conteúdo está no formato de lista do Tcl,
e a primeira palavra identifica o subsistema ou biblioteca que
relatou o erro; além desse, o conteúdo é deixado para o subsistema
ou biblioteca individual.
Para erros de banco de dados relatados por comandos
PL/Tcl, a primeira palavra é
POSTGRES, a segunda palavra é o número da versão
do PostgreSQL, e palavras adicionais são
pares nome/valor de campo que fornecem informações detalhadas sobre
o erro.
São sempre fornecidos os campos SQLSTATE,
condition, e message
(os dois primeiros representam o código de erro e o nome da condição,
conforme mostrado em Códigos de erro do PostgreSQL).
Os campos que podem estar presentes incluem
detail, hint,
context, schema,
table, column,
datatype, constraint,
statement, cursor_position,
filename, lineno, e
funcname.
Uma maneira conveniente de trabalhar com as informações de
errorCode do PL/Tcl é
carregá-las em uma matriz, de modo que os nomes dos campos se
tornem índices da matriz.
O código para fazer isto pode se parecer com
if {[catch { spi_exec $sql_command }]} {
if {[lindex $::errorCode 0] == "POSTGRES"} {
array set errorArray $::errorCode
if {$errorArray(condition) == "undefined_table"} {
# lidar com a tabela que está faltando
} else {
# lidar com algum outro tipo de erro de SQL
}
}
}
(Os dois pontos duplos especificam explicitamente que
errorCode é uma variável global.)