|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
Houve um erro de edição na Edição 30 no artigo sobre "encontrando e corrigindo registros duplicados". (Porque ninguém encontrou este erro e me notificou?) A função fixdupes() tinha uma lista de destino (target list) incorreta para a seleção de dentro da função. A função fixdupes() corrigida e completa é: create or replace function fixdupes() returns void as ' DECLARE d record; BEGIN for d in select * from rawlog group by ldate, ltime, doc, ip, method, qs, code, dsize having count(*) > 1 limit 1 loop delete from rawlog where ldate=d.ldate and ltime=d.ltime and doc=d.doc and ip=d.ip and method=d.method and qs=d.qs and code=d.code and dsize=d.dsize; insert into rawlog values (d.ip, d.ldate, d.ltime, d.method, d.doc, d.qs, d.code, d.dsize); end loop; RETURN; END; ' language 'plpgsql';
O PostgreSQL suporta linguagens confiáveis e não confiáveis para funções que rodam no servidor. Como regra geral (exceto para C) linguagens não confiáveis contém o sufixo u em seu nome. Por exemplo, plperl é confiável, mas plperlu é não confiável. Uma função escrita em uma linguagem confiável, ou seja, uma função confiável, é segura para uso genérico. Uma função escrita em uma linguagem não confiável, ou seja, uma função não confiável, pode ser escrita para ser segura, mas a possibilidade para abusos sempre existe. Tom Laine escreve, "[uma] linguagem PL-confiável deve ser capaz de definir o arbítrio de processos computacionais reservados (aritmética, padrões, entre outros), e deve ser capaz de acessar o banco de dados no mesmo nível que comandos SQL regulares. Ela não deve ser capaz de se desviar das abstrações do SQL, nem executar quaisquer operações do nível do Sistema Operacional (SO) usando os direitos do usuário postgres." Linguagens confiáveis limitam suas funcionalidades explicitamente via permissões e por interpretadores de linguagens para previnir invocar funcionalidades "perigosas". Então, uma linguagem não confiável não é, como alguns pensam, defeituosa ou uma má implementação da linguagem, mas preferivelmente, uma que permite expandir funcionalidades a serem realizadas em uma função que roda no servidor sob as permissões do superusuário postgres. Estas funcionalidades "expandidas" ou "perigosas" são largamente definidas como qualquer coisa que é executada fora do banco de dados, sobre o entendimento que, qualquer coisa que é executada fora do banco de dados poderia ser explorada para causar danos. Sistemas de E/S de arquivos, chamadas específicas do SO, gerenciamento de memória, criação de processos e comunicação interprocessos são algumas das coisas que são classificadas como perigosas. Linguagens não confiáveis devem ser explicitamente instaladas pelo superusuário do banco de dados e, permissão para criar funções e gatilhos (triggers) usando linguagens não confiáveis é limitada à usuários com direitos de superusuário. A responsabilidade da boa cidadania é colocada sobre o(s) superusuário(s). Depois de entender todos os avisos, funções não confiáveis podem ser extremamente importantes para uma aplicação. Há muitos casos autênticos e de grande valor onde linguagens e operações não confiáveis são extremamente úteis, por exemplo, enviando mensagens de correio eletrônico (email), leitura e escrita segura do sistema de arquivo e chamadas de informações do SO. Também é possível escrever uma função em uma linguagem não confiável que não faça uso de qualquer característica não confiável, por exemplo, a maioria das funções em C disponíveis no diretório contrib se encontram nesta categoria. Não Confiável não significa que a linguagem não deve ser usada. Significa que deve ser usada com precaução. Uma linguagem não confiável pode ser usada beneficamente por alguém que entende exatamente as repercussões de seu código.
Na versão 7.4, o plpython será movido de uma linguagem confiável para uma linguagem não confiável e seu nome será alterado para plpythonu. A mudança do nome enfatiza que a linguagem é agora não confiável. (Veja o artigo acima nesta edição para uma explanação sobre linguagens confiáveis e não confiáveis.) Guido Van Rossum, do time de desenvolvimento do Python, determinou que o rexec (execução restrita) se tornou fundamentalmente inseguro no python e então será removido da linguagen como a versão 2.3. A mais recente versão do plpython habilita um limitado conjunto de chamadas do python via rexec. Com o novo entendimento das fragilidades do rexec, o plpython ficou então desprotegido, não possuindo um embiente seguro, de execução restrita e foi também incompatível com o python 2.3. Kevin Jacobs cedeu uma correção para o plpython removendo as referências ao rexec e marcando a linguagem como não confiável. A correção foi aplicada à parte do desenvolvimento destinada à versão 7.4. Pessoas usando plpython provavelmente irão precisar recarregar suas funções com a linguagem mudada para plpythonu na versão 7.4. Verifique as notas e observações para o manuseio apropriado quando a versão 7.4 for liberada. Mais uma coisa, somente as pessoas com direitos de superusuário serão capazes de definir funções usando plpythonu.
Tipos de Registro (ROWTYPEs) de tabelas com colunas removidas podem ser frustrantes e confusas. Se você declara uma variável para ser do tipo de registro da sua tabela e, selecionar registros para serem inseridos nela, o conjunto da seleção e o tipo do registro de destino serão diferentes porque o tipo de registro destino ainda irá conter quaisquer colunas removidas. Um tipo de registro com colunas removidas pode ser visualizado usando \d e as colunas removidas não serão mostradas. No entanto, selecionando os dados à partir da tabela pg_attribute você pode ver onde as colunas removidas se encontram. Isto se pareceria com isso: attnum | attname | typname | case --------+------------------------------+-----------+---------------- -7 | tableoid | oid | '-7'::oid -6 | cmax | cid | '-6'::cid -5 | xmax | xid | '-5'::xid -4 | cmin | cid | '-4'::cid -3 | xmin | xid | '-3'::xid -2 | oid | oid | '-2'::oid -1 | ctid | tid | '-1'::tid 1 | col_int | int4 | '1'::int4 2 | col_timestamp | timestamp | '2'::timestamp 3 | col_float | float8 | '3'::float8 4 | col_text | text | '4'::text 5 | ........pg.dropped.5........ | text | 6 | mod_timestamp | timestamp | '6'::timestamp (13 rows) Uma função como esta não irá funcionar como esperado. O * irá selecionar os atributos 1, 2, 3, 4 e 6. No entanto, o tipo de registro (rowtype) terá os atributos 1, 2, 3, 4, 5 e 6, causando um erro de tipo (mismatch) para os tipos retornados. CREATE OR REPLACE FUNCTION testrows ( integer ) RETURNS foo AS ' DECLARE myrec foo%ROWTYPE; BEGIN SELECT INTO myrec * FROM foo WHERE foo.col_int = $1; RETURN myrec; END; ' LANGUAGE 'plpgsql'; select * from do_testrows(2); WARNING: Error occurred while executing PL/pgSQL function testrows WARNING: line 5 at select into variables ERROR: Bad timestamp external representation '2.3'Se você não recebeu um erro de tipo errado para os tipos retornados, você irá receber o seguinte erro: ERROR: Function bartest() does not exist Unable to identify a function that satisfies the given argument types You may need to add explicit typecasts Este comportamento é um problema conhecido. Uma maneira de contornar este problema é usar um tipo RECORD ao invés de um tipo ROWTYPE ou a possibilidade de designar sua lista de destino explicitamente, incluindo valores para as colunas "faltantes", ou definir um tipo de registro (ROWTYPE) que combine com sua tabela alterada usando-a ao invés do ROWTYPE da própria tabela. A correção para este problema irá requerer mudanças em todos os lugares do código onde os tipos de registro (rowtypes) são acessados. São muitos lugares. Ninguém determinou ainda uma maneira de corrigir o problema com uma alteração universal. Entretanto, tenha cuidado quando usar ROWTYPES com tabelas alteradas.
Funções plpgsql criam dependências entre objetos que se utilizam de suas consultas. Objetos incluem índices, outras funções, tabelas e visões (views). Quando uma função em plpgsql é executada pela primeira vez, um plano é criado e armazenado para as consultas descritas na função. Isto habilita o plpgsql a ser muito rápido. Se o plano possui objetos dependentes, a função não irá executar. Você deve achar que removendo um índice não deveria afetar a função, no entanto, afeta a consulta armazenada que o plano criou. Se uma consulta em uma função plpgsql armazena um plano que usa um índice e este índice é removido, então, a execução da função irá causar um erro sobre a falta de uma relação: ERROR: Relation 3912941 does not exist Removendo e recriando a função irá reparar o problema. O plano é removido quando a função é removida e, um novo plano é salvo quando a função é executada novamente.
|
|||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Comentários e Correções são bem vindos. Sugestões e contribuições de itens também são bem vindos. Envie-os!. Copyright A. Elein Mustain 2003 Traduzidos por Juliano da Silva Ignacio |