29.9. Tratamento de erro

Esta seção descreve como tratar condições excepcionais e advertências em programas com SQL incorporado. Existem várias maneiras não exclusivas para isto.

29.9.1. Definição de chamada

Um método simples para capturar os erros e advertências é definir uma ação específica a ser executada sempre que uma determinada condição ocorrer. Em geral:

EXEC SQL WHENEVER condição ação;

a condição pode ser uma das seguintes:

SQLERROR

A ação especificada é chamada sempre que ocorre um erro durante a execução da declaração SQL.

SQLWARNING

A ação especificada é chamada sempre que ocorre uma advertência durante a execução da declaração SQL.

NOT FOUND

A ação especificada é chamada sempre que a declaração SQL traz ou afeta zero linhas (Esta condição não é um erro, mas pode-se estar interessado em tratá-la de forma especial).

a ação pode ser uma das seguintes:

CONTINUE

Significa efetivamente que a condição é ignorada. É o padrão.

GOTO rótulo
GO TO rótulo

Desvia para o rótulo especificado (utilizando a declaração goto da linguagem C).

SQLPRINT

Envia uma mensagem para a saída de erro padrão. É útil em programas simples ou durante a prototipação. Não é possível configurar os detalhes da mensagem.

STOP

Chama exit(1), que termina o programa.

BREAK

Executa a declaração break da linguagem C. Deve ser utilizada apenas em laços ou nas declarações switch.

CALL nome (args)
DO nome (args)

Chama a função C com os argumentos especificados.

O padrão SQL especifica apenas as ações CONTINUE e GOTO (e GO TO).

Abaixo está mostrado um exemplo do que pode-se desejar utilizar em um programa simples. Estas declarações fazem com que seja impressa uma mensagem quando ocorre uma advertência, e interrompe o programa quando acontece um erro.

EXEC SQL WHENEVER SQLWARNING SQLPRINT;
EXEC SQL WHENEVER SQLERROR STOP;

A declaração EXEC SQL WHENEVER é uma diretiva para o pré-processador de SQL, e não uma declaração C. As ações de erro ou de advertência definidas são aplicadas a todas as declarações SQL incorporadas que aparecem abaixo do ponto onde o tratador é definido, a menos que seja definida uma ação diferente para a mesma condição entre a primeira declaração EXEC SQL WHENEVER e a declaração SQL causadora da condição, a despeito do fluxo de controle no programa C. Portanto, nenhum dos trechos de programa C abaixo produz o efeito desejado.

/*
 * ERRADO
 */
int main(int argc, char *argv[])
{
    ...
    if (verbose) {
        EXEC SQL WHENEVER SQLWARNING SQLPRINT;
    }
    ...
    EXEC SQL SELECT ...;
    ...
}
/*
 * ERRADO
 */
int main(int argc, char *argv[])
{
    ...
    set_error_handler();
    ...
    EXEC SQL SELECT ...;
    ...
}

static void set_error_handler(void)
{
    EXEC SQL WHENEVER SQLERROR STOP;
}

29.9.2. sqlca

Para permitir um tratamento de erro mais poderoso, a interface de SQL incorporado disponibiliza uma variável global com o nome de sqlca que possui a seguinte estrutura:

struct
{
    char sqlcaid[8];
    long sqlabc;
    long sqlcode;
    struct
    {
        int sqlerrml;
        char sqlerrmc[70];
    } sqlerrm;
    char sqlerrp[8];
    long sqlerrd[6];
    char sqlwarn[8];
    char sqlstate[5];
} sqlca;

Em programas com vários fluxos de execução (multithreaded), cada fluxo de execução obtém automaticamente sua própria cópia da variável sqlca. Funciona de forma semelhante à variável C global errno.

A variável sqlca cobre tanto advertências quanto erros. Se ocorrerem vários erros ou advertências durante a execução de uma declaração, então a sqlca somente vai conter informações sobre a última ocorrência.

Se não ocorrer nenhum erro na última declaração SQL executada, então sqlca.sqlcode será 0 e sqlca.sqlstate será "00000". Se ocorrer um erro ou advertência, então sqlca.sqlcode terá um valor negativo e sqlca.sqlstate será diferente de "00000". Um valor positivo em sqlca.sqlcode indica uma condição inofensiva, como a última consulta ter retornado zero linhas. sqlcode e sqlstate possuem dois esquemas de código de erro diferentes; os detalhes são mostrados abaixo.

Se a última declaração SQL for bem sucedida, então sqlca.sqlerrd[1] conterá o OID da linha processada, quando aplicável, e sqlca.sqlerrd[2] conterá o número de linhas processadas ou retornadas, se aplicável ao comando.

Em caso de erro ou de advertência, sqlca.sqlerrm.sqlerrmc contém uma cadeia de caracteres que descreve o erro. O campo sqlca.sqlerrm.sqlerrml contém o comprimento da mensagem de erro armazenada em sqlca.sqlerrm.sqlerrmc (o resultado de strlen(), sem interesse real para um programador C). Deve ser observado que algumas mensagens são muito longas para caber em uma matriz sqlerrmc de tamanho fixo, sendo truncadas.

Em caso de advertência sqlca.sqlwarn[2] é definida como W (Em todos os outros casos é definida com um valor diferente de W). Se sqlca.sqlwarn[1] for definida como W, então o valor foi truncado quando foi armazenado na variável hospedeira. sqlca.sqlwarn[0] é definida como W quando algum dos outros elementos é definido para indicar uma advertência.

Atualmente os campos sqlcaid, sqlcabc, sqlerrp, e o restante dos elementos de sqlerrd e de sqlwarn, não contêm informações úteis.

A estrutura sqlca não é definida no padrão SQL, mas é implementada em vários outros sistemas gerenciadores de banco de dados SQL. As definições são semelhantes no núcleo, mas se for desejado escrever aplicativos portáveis então deve-se investigar as diferentes implementações cuidadosamente.

29.9.3. SQLSTATE versus SQLCODE

Os campos sqlca.sqlstate e sqlca.sqlcode são dois esquemas diferentes de código de erro. Ambos são especificados pelo padrão SQL, mas SQLCODE foi marcado em obsolescência (deprecated) na edição do padrão de 1992, e removido na edição de 1999. Portanto, encoraja-se fortemente que os novos aplicativos utilizem SQLSTATE.

SQLSTATE é uma matriz de cinco caracteres. Os cinco caracteres contêm dígitos ou letras maiúsculas que representam códigos de vários erros e de condições de advertência. SQLSTATE possui um esquema hierárquico: os dois primeiros caracteres indicam a classe geral da condição, e os três últimos caracteres indicam a subclasse da condição geral. O status de bem-sucedido é indicado pelo código 00000. A maior parte dos códigos de SQLSTATE são definidos pelo padrão SQL. O servidor PostgreSQL suporta nativamente os códigos de erro SQLSTATE; portanto, pode ser obtido um alto grau de consistência utilizando este esquema de código de erro através de todos os aplicativos. Para obter informações adicionais deve ser consultado o Apêndice A.

O esquema de código de erro obsoleto SQLCODE é um inteiro simples. O valor 0 indica bem-sucedido, um valor positivo indica bem-sucedido com informação adicional, e um valor negativo indica um erro. O padrão SQL define apenas o valor positivo +100, indicando que o último comando retornou ou afetou zero linhas, e não especifica nenhum valor negativo. Portanto, este esquema pode obter apenas uma portabilidade pobre, e não possui uma atribuição de código hierárquica. Historicamente, o pré-processador de SQL incorporado do PostgreSQL tem atribuído alguns valores específicos de SQLCODE para seu uso, os quais estão listados abaixo junto com seus valores numéricos e nomes simbólicos. Deve ser lembrado que estes valores não são portáveis para outras implementações do padrão SQL. Para simplificar a migração dos aplicativos para o esquema SQLSTATE, também é mostrado o SQLSTATE correspondente. Entretanto, não existe nenhum mapeamento um-para-um ou um-para-muitos entre estes dois esquemas (na verdade, é muitos-para-muitos), portanto deve ser consultada a lista de SQLSTATE global no Apêndice A para cada caso.

Abaixo estão mostrados os valores de SQLCODE atribuídos:

-12 (ECPG_OUT_OF_MEMORY)

Indica que a memória virtual encontra-se exaurida. (SQLSTATE YE001)

-200 (ECPG_UNSUPPORTED)

Indica que o pré-processador gerou algo que a biblioteca não tem conhecimento. Talvez esteja sendo usada uma versão do pré-processador incompatível com a da biblioteca. (SQLSTATE YE002)

-201 (ECPG_TOO_MANY_ARGUMENTS)

Significa que o comando especificou mais variáveis hospedeiras do que o comando espera. (SQLSTATE 07001 ou 07002)

-202 (ECPG_TOO_FEW_ARGUMENTS)

Significa que o comando especificou menos variáveis hospedeiras do que o comando espera. (SQLSTATE 07001 ou 07002)

-203 (ECPG_TOO_MANY_MATCHES)

Significa que a consulta retornou várias linhas, mas a declaração somente está preparada para armazenar uma linha de resultado (por exemplo, porque as variáveis especificadas não são matrizes). (SQLSTATE 21000)

-204 (ECPG_INT_FORMAT)

A variável hospedeira é do tipo int, e o dado no banco de dados é de um tipo diferente e contém um valor que não pode ser interpretado como um int. A biblioteca utiliza strtol() para esta conversão. (SQLSTATE 42804)

-205 (ECPG_UINT_FORMAT)

A variável hospedeira é do tipo unsigned int e o dado no banco de dados é de um tipo diferente e contém um valor que não pode ser interpretado como um unsigned int. A biblioteca utiliza strtoul() para esta conversão. (SQLSTATE 42804)

-206 (ECPG_FLOAT_FORMAT)

A variável hospedeira é do tipo float e o dado no banco de dados é de um tipo diferente e contém um valor que não pode ser interpretado como um float. A biblioteca utiliza strtod() para esta conversão. (SQLSTATE 42804)

-207 (ECPG_CONVERT_BOOL)

Significa que a variável hospedeira é do tipo bool e o dado no banco de dados não é nem 't' nem 'f'. (SQLSTATE 42804)

-208 (ECPG_EMPTY)

A declaração enviada para o servidor PostgreSQL estava vazia (Normalmente isto não pode acontecer em um programa com SQL incorporado, portanto pode indicar um erro interno). (SQLSTATE YE002)

-209 (ECPG_MISSING_INDICATOR)

Foi retornado um valor nulo e não foi especificada uma variável indicadora. (SQLSTATE 22002)

-210 (ECPG_NO_ARRAY)

Foi utilizada uma variável comum em um local que requer uma matriz. (SQLSTATE 42804)

-211 (ECPG_DATA_NOT_ARRAY)

O banco de dados retornou uma variável comum em um local que requer um valor matricial. (SQLSTATE 42804)

-220 (ECPG_NO_CONN)

O programa tentou acessar uma conexão que não existe. (SQLSTATE 08003)

-221 (ECPG_NOT_CONN)

O programa tentou acessar uma conexão que existe, mas que não está aberta (Isto é um erro interno). (SQLSTATE YE002)

-230 (ECPG_INVALID_STMT)

A declaração que está se tentando utilizar não foi preparada. (SQLSTATE 26000)

-240 (ECPG_UNKNOWN_DESCRIPTOR)

Não foi encontrado o descritor especificado. A declaração que está se tentando utilizar não foi preparada. (SQLSTATE 33000)

-241 (ECPG_INVALID_DESCRIPTOR_INDEX)

O índice descritor especificado está fora do intervalo. (SQLSTATE 07009)

-242 (ECPG_UNKNOWN_DESCRIPTOR_ITEM)

Foi requisitado um item descritor inválido (Este é um erro interno). (SQLSTATE YE002)

-243 (ECPG_VAR_NOT_NUMERIC)

Durante a execução da declaração dinâmica o banco de dados retornou um valor numérico e a variável hospedeira não é numérica. (SQLSTATE 07006)

-244 (ECPG_VAR_NOT_CHAR)

Durante a execução da declaração dinâmica o banco de dados retornou um valor não numérico e a variável hospedeira é numérica. (SQLSTATE 07006)

-400 (ECPG_PGSQL)

Algum erro causado pelo servidor PostgreSQL. A mensagem contém a mensagem de erro do servidor PostgreSQL.

-401 (ECPG_TRANS)

O servidor PostgreSQL sinalizou que não pode iniciar, efetivar ou desfazer a transação. (SQLSTATE 08007)

-402 (ECPG_CONNECT)

A tentativa de conexão com o banco de dados não foi bem-sucedida. (SQLSTATE 08001)

100 (ECPG_NOT_FOUND)

É uma condição inofensiva, indicando que o último comando trouxe ou processou zero linhas, ou que se chegou ao fim do cursor. (SQLSTATE 02000)

SourceForge.net Logo CSS válido!