Documentação do PostgreSQL 8.0.0 | ||||
---|---|---|---|---|
Anterior | Início | Capítulo 35. PL/pgSQL - Linguagem procedural SQL | Fim | Próxima |
Todas as expressões utilizadas nas instruções do PL/pgSQL são processadas utilizando o executor de SQL regular do servidor. Na verdade, um comando como
SELECT expressão
é executado utilizando o gerenciador da Interface de Programação do Servidor (SPI). Antes da avaliação, as ocorrências de identificadores variáveis do PL/pgSQL são substituídas por parâmetros, e os valores verdadeiros das variáveis são passados para o executor na matriz de parâmetros. Isto permite que o plano de comando para o SELECT seja preparado uma única vez, e depois reutilizado nas avaliações seguintes.
A avaliação feita pelo analisador principal do PostgreSQL produz alguns efeitos colaterais na interpretação de valores constantes. Visto em detalhes existe diferença entre o que estas duas funções fazem:
CREATE FUNCTION logfunc1(logtxt text) RETURNS timestamp AS $$ BEGIN INSERT INTO logtable VALUES (logtxt, 'now'); RETURN 'now'; END; $$ LANGUAGE plpgsql;
e
CREATE FUNCTION logfunc2(logtxt text) RETURNS timestamp AS $$ DECLARE curtime timestamp; BEGIN curtime := 'now'; INSERT INTO logtable VALUES (logtxt, curtime); RETURN curtime; END; $$ LANGUAGE plpgsql;
No caso da função logfunc1, o analisador principal do PostgreSQL sabe, ao preparar o plano para o comando INSERT, que a cadeia de caracteres 'now' deve ser interpretada como timestamp, porque a coluna de destino na tabela logtable é deste tipo, e por isso cria uma constante a partir de 'now' contendo a data e hora da análise. Depois, esta constante é utilizada em todas as chamadas à função logfunc1 durante toda a sessão. É desnecessário dizer que não é este o comportamento o desejado pelo programador.
No caso da função logfunc2, o analisador principal do PostgreSQL não sabe o tipo que 'now' deve se tornar e, portanto, retorna um valor de dado do tipo text contendo a cadeia de caracteres now. Durante as atribuições seguintes à variável local curtime, o interpretador do PL/pgSQL irá converter a cadeia de caracteres para o tipo timestamp, chamando as funções text_out e timestamp_in para fazer a conversão. Portanto, a data e hora computada é atualizada a cada execução, como esperado pelo programador.
A natureza mutável das variáveis registro também apresenta um problema semelhante. Quando campos de uma variável registro são utilizados em expressões ou instruções, os tipos de dado dos campos não devem mudar entre chamadas à mesma expressão, uma vez que a expressão é planejada utilizando o tipo de dado presente quando a expressão é encontrada pela primeira vez. Deve-se ter isto em mente ao escrever procedimentos de gatilhos que tratam eventos para mais de uma tabela; quando for necessário, pode ser utilizado EXECUTE para evitar este problema.