Bom dia!

Fabiano,

> Explique porque você precisa dessa PL, qual a necessidade original,
> talvez tenha outras maneiras de resolver.
> Porque os comandos que já estão prontos precisam passar por ela?

Trabalho desenvolvendo um sistema bem robusto, com diversos módulos e
"sub-sistemas". Grande parte desse sistema já está pronto,
praticamente todo feito em PHP.
Há um sistema de logs, também feito em PHP, que funciona através de
uma função que "quebra" a consulta, gravando as alterações (semelhante
a OLD e NEW das trigger). Todas as consultas desse sistema passam por
esta função, para tratar os dados. Além das alterações, nome da tabela
e hora, esse sistema de logs precisa gravar alguns parâmetros, como o
id do usuário atualmente logado no sistema, assim como o deck
(ambiente).
Em PHP, o sistema funciona com apenas 1 query de cada vez, falhando
nos casos onde há várias juntas (select * ... ; insert ... ;), sem
falar que gera uma lentidão tremenda.

Decidimos recriar esta função através de triggers de update, insert e
delete, para facilitar/agilizar a criação de logs.
Até aqui tudo bem, o problema são os parâmetros que precisam ser
passados via PHP.
Como não é possível parametrizar as triggers, resolvi criar uma função
(aquela que mandei numa resposta anterior). Esta função recebe a
string de querys, juntamente com os parâmetros. Os parâmetros são
gravados uma tabela(log_usuario) e a query é executada. Dentro da
função da trigger, é feito um select nesta tabela(log_usuario), para
receber o usuário/deck atual. Tudo é registrado na tabela final de
logs (através da trigger).

Resolvi usar uma função para isso tudo pela necessidade de parâmetros,
e pelo fato de serem muitos usuários conectados ao mesmo tempo. Neste
caso, as alterações são gravadas apenas no final da função, não
deixando possibilidade de um usuário sobrescrever o id do outro, na
tabela "log_usuario".

Já pensei em separar tudo, deixando apenas begin/commit no início e
final, mas infelizmente o begin/commit já é eventualmente utilizado no
sistema, podendo gerar conflito (ou é possível usar algum tipo de
cascata?)

Já verifiquei vários sistemas de table audit na internet, e todos tem
o mesmo problema: não aceitam parâmetros externos.

Sujestões de alteração ou outros modos de realizar o mesmo
procedimento são bem vindas.

Desde já, agradeço pela colaboração de todos.

Atenciosamente,
Pedro Cavalheiro



Em 2 de setembro de 2011 02:04, Fabiano Machado Dias
<[email protected]> escreveu:
> Em 1/9/2011 22:04, Pedro Cavalheiro escreveu:
>> Boa noite a todos!
>>
>> Fabiano,
>>
>>> O seu retorno seria os registros do "select"? E se alguém passar um passar
>>> um comando "select * from tabela; insert into tabela..." ? O retorno seria o
>>> que?
>> Sim, o retorno deve ser os registros do select. No caso de alguém
>> passar uma query multipla, acredito que o mais fácil seria levar em
>> conta apenas a última (ignorando os retornos anteriores). Até por isso
>> comentei que pode funcionar de um jeito ou de outro (retornando tudo
>> ou apenas a última consulta, o que for mais fácil para definir). No
>> caso de insert, update ou delete, não é necessário retornar nada.
>>
>>> O retorno como está não funciona para trazer vários registros, para isso
>>> você deve usar um setof com record ou type.
>> Sim, estou ciente disso. Justamente por isso que entrei em contato com
>> o grupo, não sei como prosseguir. Tentei definir de diversos modos
>> diferentes a combinação de setof, record, entre outros, mas sempre
>> recebia algum erro.
>> Não entendi bem a sintaxe que precisa ser definida para receber o
>> retorno em tabela.
>> Queria algo como adicionar os resultados da query numa variável, e
>> retornar essa variável (isso é apenas uma explicação, não sei se é
>> possível em pgplsql).
>>
>> Infelizmente, não tenho como criar uma função para criação das querys.
>> Já existe um sistema em funcionamento, com diversos consultas
>> "gigantescas" que tornam a ideia inviável.
>> O único modo de fazer isto é definindo retorno por type? Quais as
>> exigências deste tipo? Não existe algum modo mais prático, sem nenhum
>> tipo de "filtro", para retornar uma tabela de uma consulta?
>>
>> Desde já, agradeço pela ajuda.
>>
>> Abraços a todos.
>>
>> Atenciosamente,
>> Pedro Cavalheiro
>
>
> Explique porque você precisa dessa PL, qual a necessidade original,
> talvez tenha outras maneiras de resolver.
>
> Porque os comandos que já estão prontos precisam passar por ela?
>
> De qualquer maneira segue um exemplo abaixo de uma PL com type
>
> DROP TYPE IF EXISTS fnc.funcao2_retornotype_retorno CASCADE;
> CREATE TYPE fnc.funcao2_retornotype_retorno AS (
> codigoVARCHAR,
> descricao VARCHAR);
> --Coloco isso para que não exista conflito de que o mesmo type seja
> usado por outra pl, é só uma convenção minha se não quiser usar não precisa.
> */
> /*
> CREATE OR REPLACE FUNCTION fnc.funcao2_retornotype(pTipo INTEGER)
> RETURNS SETOF */fnc.funcao2_retornotype_retorno/*AS
> $$
> DECLARE
> */rRetorno/**/fnc.funcao2_retornotype_retorno/**/; /*
> BEGIN
> IF pTipo = 1 THEN
> RETURN QUERY (SELECT codigo,descricao FROM situacaonfe ORDER BY codigo);
> ELSIF pTipo = 2 THEN
> FOR */rRetorno/*IN SELECT codigo,descricao FROM situacaonfe ORDER BY codigo
> LOOP
> RETURN NEXT */rRetorno/*;
> END LOOP;
> ELSE
> RAISE EXCEPTION 'Escolha um tipo(1 ou 2)!';
> END IF;
> RETURN;
> END;
> $$
> LANGUAGE plpgsql;
>
>
> Exemplo da chamada:
>
> SELECT * FROM fnc.funcao2_retornotype(2);
> SELECT fnc.funcao2_retornotype(2);
> SELECT (fnc.funcao2_retornotype(2)).descricao;
>
>  * Português - detectado
>  * Inglês
>  * Português
>
>  * Inglês
>  * Português
>
> <javascript:void(0);>
> _______________________________________________
> pgbr-geral mailing list
> [email protected]
> https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
>
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Responder a