7.1.4. Mensagens e Exceções

O comando RAISE pode ser usado para reportar mensagens, que são associadas a níveis de severidade: DEBUG, LOG, INFO, NOTICE, WARNING, e EXCEPTION.

O nível EXCEPTION lança uma exceção (ou erro), que aborta a execução da função, abortando também a transação na qual a função se encontra. Os outros cinco níveis apenas emitem uma mensagem com diferentes prioridades1.

Vamos utilizar o comando RAISE junto com testes condicionais para verificar se os argumentos informados à função my_distance correspondem ao tipo geométrico ST_Point e, se esses pontos encontram-se no mesmo sistema de referência espacial. A nova definição da função my_distance pode ser vista abaixo.

CREATE OR REPLACE FUNCTION my_distance(first GEOMETRY, second GEOMETRY)
RETURNS NUMERIC
AS
$$
    DECLARE
        dx NUMERIC DEFAULT 0.0;
        dy NUMERIC DEFAULT 0.0;
        d  NUMERIC DEFAULT 0.0;
    BEGIN
        IF( (ST_GeometryType(first) <> 'ST_Point') OR
            (ST_GeometryType(second) <> 'ST_Point') ) THEN
            RAISE EXCEPTION 'Tipos geométricos inválidos!';
        END IF;

        IF(ST_SRID(first) <> ST_SRID(second)) THEN
            RAISE EXCEPTION 'Pontos com SRIDs diferentes!';
        END IF;

        dx := ST_X(first) - ST_X(second);
        dy := ST_Y(first) - ST_Y(second);


        RAISE NOTICE 'dx: %', dx;
        RAISE NOTICE 'dy: %', dy;

        d := sqrt(power(dx, 2) + power(dy, 2));

        RETURN d;
    END;
$$
LANGUAGE plpgsql;

Desta vez, se não respeitarmos os tipos geométricos, a função irá produzir uma mensagem de erro e a função será interrompida:

SELECT my_distance(
    ST_GeometryFromText('LINESTRING(0 0, 1 1)', 4326),
    ST_GeometryFromText('POINT(1 1)', 4326));

Saída:

ERROR:  Tipos geométricos inválidos!

Da mesma forma, se informarmos pontos com diferentes SRIDs, uma mensagem será produzida informando o erro e a função será interrompida:

SELECT my_distance(
    ST_GeometryFromText('POINT(0 0)', 29193),
    ST_GeometryFromText('POINT(1 1)', 4326));

Saída:

ERROR:  Pontos com SRIDs diferentes!

Caso a função seja chamada com argumentos válidos, além do resultado, será produzida uma mensagem (NOTICE):

SELECT my_distance(
ST_GeometryFromText('POINT(0 0)', 4326),
ST_GeometryFromText('POINT(1 1)', 4326));

Saída:

NOTICE:  dx: -1
NOTICE:  dy: -1
my_distance
--------------------
1.4142135623730950
(1 row)

Outro detalhe a ser notado no exemplo é o uso do caractere % dentro das mensagens:

RAISE NOTICE 'dx: %', dx;
RAISE NOTICE 'dy: %', dy;

No comando RAISE, o texto de uma mensagem pode conter o caractere especial %, que é substituído pelo valor de um literal ou variável informado após o texto da mensagem. No exemplo acima, os valores das variáveis dx e dy foram substituídos pelo símbolo % nas respectivas linhas.

Os níveis de severidade também estão associados a alguns comportamentos importantes. Por exemplo, RAISE NOTICE envia mensagem imediatamente, assim que a linha é executada. Já o comando RAISE NOTIFY aguarda a transação que contém a execução da função terminar, de forma que a mensagem pode não ser mostrada se a transação falhar e for desfeita (rollback).

Notas

1

Existem variáveis de configuração do servidor que controlam se as mensagens são escritas no log do próprio servidor. Veja no manual do PostgreSQL as variáveis log_min_messages e client_min_messages para maiores detalhes.