42.8. Tratamento de erro em PL/Tcl #

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.)