Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres

2008-09-18 Por tôpico William Leite Araújo
2008/9/18 Mozart Hasse [EMAIL PROTECTED]



 -- Original Message --
  From:  William Leite Araújo [EMAIL PROTECTED]
 
  2008/9/17 Mozart Hasse [EMAIL PROTECTED]
 
   (...)
   Atribuir o NEW nas triggers de BEFORE até que aparentemente funcionou,
   porém
   tive de deixar todas as triggers como AFTER para resolver outros
   problemas...
 
 
  Bom, novamente vou alertar que NUNCA, no postgresql, atribuir valores
 ao
  registro NEW ou OLD num gatilho AFTER funcionará. A idéia do AFTER é
 fazer
  alterações em outras tabelas, e não na que gerou o evento.

 Sim, eu sei, troquei as atribuições por UPDATES diretos na tabela ao passar
 para triggers AFTER.


   Bom, a coisa até que andou, não tenho mais aquele erro do record 'new'
 is
   not assigned yet, só que agora resta descobrir como se implementa em
   Postgres a funcionalidade da qual as triggers originais dependiam:
   identificar se a chamada atual da trigger function foi disparada de um
   UPDATE/INSERT/DELETE da aplicação ou da própria trigger...
 
Tive problemas com isso uma vez, e acho que uma possivel solução
 seria
  marcar isso numa tabela temporária pela regra da VIEW. É possível
 executar
  mais de uma ação na regra.
   Por exemplo:
 
CREATE RULE regra_do_cao ON INSERT TO [nome da view] DO INSTEAD *(*
   INSERT INTO [tabela temporaria de marcação] VALUES (...);
   INSERT INTO [tabela real] VALUES (...) *);*

 O problema é que eu tenho de marcar a tabela temporária de _dentro_ da
 trigger...

 Explicando melhor: eu preciso fazer, por conta do mesmo comando de origem,
 duas coisas:

 * ajustar ponteiros dos registros anterior, atual e posterior. A trigger
 function pode alterar registros (incluindo o registro original) por conta
 da
 operação original, e essas alterações não devem disparar novamente a
 trigger (ou pelo menos devem notar que é uma chamada recursiva e sair sem
 fazer nada);



Nesse sentido, existe a possibilidade de desabilitar o trigger durante a
execução do mesmo (caso o usuário tenha essa permissão ou o trigger seja
SECURITY DEFINNER). Tipo :
ALTER TABLE [tabela] DISABLE TRIGGER xxx;
 (... comandos pra fazer as alterações ...)
ALTER TABLE [tabela] ENABLE TRIGGER xxx;

Não sei dizer se desabilitará para todas as transações (acredito que
não) ou somente para a corrente.







 * depois de garantir que os ponteiros estão em ordem, eu tenho de disparar
 uma function (recálculo de registros posteriores) uma única vez a cada
 comando 'externo' à trigger, e isso só pode acontecer _depois_ de atualizar
 o registro original. Esta function pode incluir, alterar e excluir
 registros
 por conta da operação original. Essas operações não devem disparar
 novamente a própria function.


Bom, essa function (por ser apenas uma) pode então iniciar seu
processamento marcando em uma tabela temporária que está em execução para
evitar que ela seja novamente executada, certo?



 O desejável seria que as atualizações da function de recálculo se
 aproveitassem da parte de atualização de ponteiros das trigger functions,
 pois há diversos pontos de atualização e a função depende da integridade
 dos ponteiros após cada operação. A replicação dessa regra em cada um dos
 lugares em que a tabela é atualizada tornaria o código horrivelmente
 complicado, absurdamente redundante e radicalmente difícil de manter.


Concordo. Que coisa mais louca...



 Eu atualizo a tabela de marcação em Oracle na primeira atualização
 proveniente de qualquer trigger, a fim de saber que as chamadas
 subsequentes
 devem ser ignoradas ou devem fazer apenas as operações que não causam
 recursão.


E isso não funciona com o Postgresql, numa tabela temporária? O nome da
tabela temporária pode conter, por exemplo, o ID da transação !?



 Se eu entrar na trigger com a tabela já marcada (conforme sua sugestão),
 não vou saber quando posso e quando não posso atualizar os registros
 anteriores e posteriores ou disparar a rotina de recálculo.
 Se eu puser a chamada dessa rotina de recálculo como comando posterior à
 atualização do registro na declaração da RULE, ainda assim terei problemas
 com a recursividade, pois os comandos da trigger e da function de recálculo
 vão disparar as triggers eternamente.


 Bom, eu poderia tentar tirar tudo das triggers e fazer rules que chamam um
 monte de functions numa certa sequência, o que teoricamente acabaria com o
 problema da recursividade. A questão é... não tem um jeito mais simples ?!


Acho que não resolveria o problema. Apenas mudaria o ponto onde ele
ocorreria...


-- 
William Leite Araújo
Analista de Banco de Dados - QualiConsult
___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral


Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres

2008-09-18 Por tôpico Osvaldo Kussama
Em 18/09/08, Mozart Hasse[EMAIL PROTECTED] escreveu:


 -- Original Message --
 From:  William Leite Araújo[EMAIL PROTECTED]

 2008/9/17 Mozart Hasse [EMAIL PROTECTED]

  (...)
  Atribuir o NEW nas triggers de BEFORE até que aparentemente funcionou,
  porém
  tive de deixar todas as triggers como AFTER para resolver outros
  problemas...


 Bom, novamente vou alertar que NUNCA, no postgresql, atribuir valores
 ao
 registro NEW ou OLD num gatilho AFTER funcionará. A idéia do AFTER é
 fazer
 alterações em outras tabelas, e não na que gerou o evento.

 Sim, eu sei, troquei as atribuições por UPDATES diretos na tabela ao passar
 para triggers AFTER.


  Bom, a coisa até que andou, não tenho mais aquele erro do record 'new'
 is
  not assigned yet, só que agora resta descobrir como se implementa em
  Postgres a funcionalidade da qual as triggers originais dependiam:
  identificar se a chamada atual da trigger function foi disparada de um
  UPDATE/INSERT/DELETE da aplicação ou da própria trigger...

   Tive problemas com isso uma vez, e acho que uma possivel solução
 seria
 marcar isso numa tabela temporária pela regra da VIEW. É possível
 executar
 mais de uma ação na regra.
  Por exemplo:

   CREATE RULE regra_do_cao ON INSERT TO [nome da view] DO INSTEAD *(*
  INSERT INTO [tabela temporaria de marcação] VALUES (...);
  INSERT INTO [tabela real] VALUES (...) *);*

 O problema é que eu tenho de marcar a tabela temporária de _dentro_ da
 trigger...

 Explicando melhor: eu preciso fazer, por conta do mesmo comando de origem,
 duas coisas:

 * ajustar ponteiros dos registros anterior, atual e posterior. A trigger
 function pode alterar registros (incluindo o registro original) por conta da
 operação original, e essas alterações não devem disparar novamente a
 trigger (ou pelo menos devem notar que é uma chamada recursiva e sair sem
 fazer nada);

 * depois de garantir que os ponteiros estão em ordem, eu tenho de disparar
 uma function (recálculo de registros posteriores) uma única vez a cada
 comando 'externo' à trigger, e isso só pode acontecer _depois_ de atualizar
 o registro original. Esta function pode incluir, alterar e excluir registros
 por conta da operação original. Essas operações não devem disparar
 novamente a própria function.


Veja a solução proposta pelo Pavel Stehule para evitar chamadas recursivas:
http://www.nabble.com/Synchronize-two-similar-tables%3A-recursive-triggers-to19545281.html


 O desejável seria que as atualizações da function de recálculo se
 aproveitassem da parte de atualização de ponteiros das trigger functions,
 pois há diversos pontos de atualização e a função depende da integridade
 dos ponteiros após cada operação. A replicação dessa regra em cada um dos
 lugares em que a tabela é atualizada tornaria o código horrivelmente
 complicado, absurdamente redundante e radicalmente difícil de manter.

 Eu atualizo a tabela de marcação em Oracle na primeira atualização
 proveniente de qualquer trigger, a fim de saber que as chamadas subsequentes
 devem ser ignoradas ou devem fazer apenas as operações que não causam
 recursão.

 Se eu entrar na trigger com a tabela já marcada (conforme sua sugestão),
 não vou saber quando posso e quando não posso atualizar os registros
 anteriores e posteriores ou disparar a rotina de recálculo.
 Se eu puser a chamada dessa rotina de recálculo como comando posterior à
 atualização do registro na declaração da RULE, ainda assim terei problemas
 com a recursividade, pois os comandos da trigger e da function de recálculo
 vão disparar as triggers eternamente.

 Bom, eu poderia tentar tirar tudo das triggers e fazer rules que chamam um
 monte de functions numa certa sequência, o que teoricamente acabaria com o
 problema da recursividade. A questão é... não tem um jeito mais simples ?!



Osvaldo
___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral


Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres

2008-09-16 Por tôpico William Leite Araújo
2008/9/15 Mozart Hasse [EMAIL PROTECTED]

 Olá,

 Estou tentando converter um conjunto de triggers/stored procedures de
 Oracle 9
 para Postgres 8.3.
 Julgo ser necessário dar uma visão geral para dar idéia do tamanho da
 encrenca:

 A trigger tem a intenção de atualizar os valores de alguns campos (saldo
 anterior e data inicial do próximo registro) no registro recém incluído, de
 forma a deixar o registro incluído com valores coerentes com os registros
 anteriores e posteriores, segundo um determinado critério de ordenação.
 Visando proteger a integridade da tabela, é importantíssimo que os usuários
 e a aplicação não consigam atualizar dados diretamente na tabela sem passar
 pela trigger. Aliás, acho que o usuário/desenvolvedor ficará ainda mais
 feliz se nem souber que existe uma trigger que corrige os valores para ele.

 Devido à natureza recursiva dessa modelagem (eu preciso alterar dados do
 próprio registro e em alguns casos dar mais de um UPDATE sobre o mesmo
 registro), o Oracle não me permitia alterar o registro diretamente de
 dentro
 da trigger. A solução adotada em Oracle foi a seguinte:

 * Mover a tabela original para outro schema e protegê-la contra alterações
 feitas diretamente pelos usuários ou pela aplicação;
 * Criar uma view com o nome da tabela original;
 * criar triggers do tipo INSTEAD OF UPDATE or INSERT or DELETE na View;
 * dar os UPDATEs na tabela de fato ou na view, usando para isso SELECTs na
 view quando necessário.

 A solução, apesar de complexa, resolveu o problema em Oracle com ótimo
 desempenho. Eu tenho uma versão igualmente eficiente para SQL Server, só
 que
 preferi não usá-la como referência porque o SQL Server não se importa em
 fazer alterações repetidas e recursivas sobre o mesmo registro.

 Falta fazer o mesmo em Postgres...

 O problema é que eu não consigo achar meios de implementar a mesma
 funcionalidade:

 * se eu tento criar triggers com comandos UPDATE/DELETE diretamente sobre a
 tabela, o Postgres dá aquele erro infame: 'ERROR: record new is not
 assigned yet'. Suponho que o problema seja similar ao do Oracle. Estou
 certo?

 * se eu tento usar a mesma solução adotada no Oracle, não consigo criar a
 trigger sobre a view. Exemplo:

 -- tabela original movida para outro schema
 CREATE TABLE gestao.mvtoestq (.../* mais de 50 campos */ );

 -- view que eu gostaria de atualizar pela aplicação
 create or replace view public.mvtoestq as SELECT * FROM gestao.mvtoestq;

 -- trigger function mirabolante que atualiza a view ou a tabela conforme
 uma
 regra de negócio esdrúxula
 create or replace FUNCTION finMvtoEstq() returns trigger as
 /* 250 linhas de código que chamam uma SP com mais 800 linhas cheias de
 SELECTs monstruosos e UPDATEs mirabolantes */
 ...
 UPDATE public.mvtoestq SET...
 ...
 UPDATE gestao.mvtoestq SET...
 ...
 ;

 -- trigger sobre a view
 CREATE TRIGGER tr_mvtoestq_ins
  instead of INSERT
  ON public.mvtoestq
  FOR EACH ROW
  EXECUTE PROCEDURE finmvtoestq();

 Neste último comando o Postgres me retorna:

 ERROR:  syntax error at or near instead
 LINE 2:   instead of INSERT


Não há, no postgresql, trigger sobre a view. Use CREATE RULE. É até
melhor, porque uma regra pode ser aplicada a um SELECT também.




 Finalmente as perguntas:
 1. O que eu faço agora?
 2. Tem como contornar o problema sem precisar de uma View ?
 3. Tem algum jeito de implementar de maneira equivalente ao Oracle ?
 4. Tem algum outro jeito que funcione em Postgres ?
 5. Alguém já passou por algo parecido ? Qual a solução adotada ?

 Atualmente todos os comandos das triggers e stored procedures estão
 embutidos
 no código da aplicação e são ativados somente quando ela usa Postgres.
 Isso complica imensamente a manutenção, dificulta a depuração e aumenta
 muito a chance de erros, além de dar ao usuário e ao desenvolvedor a chance
 (raramente desperdiçada) de deixar a tabela com dados inconsistentes.

 Grato pela atenção,


 Mozart Hasse


 ___
 pgbr-geral mailing list
 pgbr-geral@listas.postgresql.org.br
 https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral




-- 
William Leite Araújo
Analista de Banco de Dados - QualiConsult
___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral


Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres

2008-09-16 Por tôpico Emerson Casas Salvador
Mozart Hasse escreveu:
 Olá,

 Estou tentando converter um conjunto de triggers/stored procedures de Oracle 9
 para Postgres 8.3.
 Julgo ser necessário dar uma visão geral para dar idéia do tamanho da
 encrenca:

 A trigger tem a intenção de atualizar os valores de alguns campos (saldo
 anterior e data inicial do próximo registro) no registro recém incluído, de
 forma a deixar o registro incluído com valores coerentes com os registros
 anteriores e posteriores, segundo um determinado critério de ordenação.

pq vc não faz uma trigger *Before Insert* e muda o valor antes dele ser 
gravado?

assim
new.nomedocampo = (SELECT blablabla);

e outra trigger no after delete para atualizar (um laço) os registros 
afetados (acredito que sejam todos os posteriores)

--
Esta mensagem foi verificada pelo sistema de Anti-virus da SJB Solados.

___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral


Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres

2008-09-16 Por tôpico Mozart Hasse
Emerson,

 Mozart Hasse escreveu:
  A trigger tem a intenção de atualizar os valores de alguns campos
(saldo
  anterior e data inicial do próximo registro) no registro recém
incluído, de
  forma a deixar o registro incluído com valores coerentes com os
registros
  anteriores e posteriores, segundo um determinado critério de
ordenação.
 
 pq vc não faz uma trigger *Before Insert* e muda o valor antes dele ser 
 gravado?
 
 assim
 new.nomedocampo = (SELECT blablabla);
 
 e outra trigger no after delete para atualizar (um laço) os registros 
 afetados (acredito que sejam todos os posteriores)

O problema é que eu teria de aplicar uma regra de negócio complicadíssima
sobre o registro inserido/alterado (adaptando umas 500 linhas de querys para
consultar os outros registros incluindo o NEW) e manter essa mesmíssima regra
duplicada em outro trecho que atualiza os registros posteriores ao que foi
atualizado (independente do NEW/OLD). Corro ainda o risco de precisar
triplicar essa regra ao fazer uma trigger específica para o UPDATE e outra
para o DELETE. 

Eu já tenho um roteiro de testes bastante extenso para validar isso
considerando que a regra de negócio está em um lugar só, e se eu precisar
duplicar o código vou tornar meu processo de homologação ainda mais
complexo, além de piorar *muito* a minha manutenção daqui por diante.

Posso tentar fazer isso pelo ganho esperado em desempenho e redução no
tráfego de rede, mas vai ser bem difícil vender essa idéia (duplicação de
regra de negócio) devido ao custo de manutenção posterior, pois vai
exatamente e radicalmente contra todos os nossos esforços.

Agradeço a sugestão, em último caso vou segui-la, porém ainda estou à
procura de uma opção que não dê ao Postgres um diferencial tão negativo
frente ao SQL Server/Oracle.

Atenciosamente,


Mozart Hasse


___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral


Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres

2008-09-16 Por tôpico William Leite Araújo
Criando regras de INSERT e UPDATE funciona?

2008/9/16 Mozart Hasse [EMAIL PROTECTED]

 Emerson,

  Mozart Hasse escreveu:
   A trigger tem a intenção de atualizar os valores de alguns campos
 (saldo
   anterior e data inicial do próximo registro) no registro recém
 incluído, de
   forma a deixar o registro incluído com valores coerentes com os
 registros
   anteriores e posteriores, segundo um determinado critério de
 ordenação.
 
  pq vc não faz uma trigger *Before Insert* e muda o valor antes dele ser
  gravado?
 
  assim
  new.nomedocampo = (SELECT blablabla);
 
  e outra trigger no after delete para atualizar (um laço) os registros
  afetados (acredito que sejam todos os posteriores)

 O problema é que eu teria de aplicar uma regra de negócio complicadíssima
 sobre o registro inserido/alterado (adaptando umas 500 linhas de querys
 para
 consultar os outros registros incluindo o NEW) e manter essa mesmíssima
 regra
 duplicada em outro trecho que atualiza os registros posteriores ao que foi
 atualizado (independente do NEW/OLD). Corro ainda o risco de precisar
 triplicar essa regra ao fazer uma trigger específica para o UPDATE e outra
 para o DELETE.

 Eu já tenho um roteiro de testes bastante extenso para validar isso
 considerando que a regra de negócio está em um lugar só, e se eu precisar
 duplicar o código vou tornar meu processo de homologação ainda mais
 complexo, além de piorar *muito* a minha manutenção daqui por diante.

 Posso tentar fazer isso pelo ganho esperado em desempenho e redução no
 tráfego de rede, mas vai ser bem difícil vender essa idéia (duplicação de
 regra de negócio) devido ao custo de manutenção posterior, pois vai
 exatamente e radicalmente contra todos os nossos esforços.

 Agradeço a sugestão, em último caso vou segui-la, porém ainda estou à
 procura de uma opção que não dê ao Postgres um diferencial tão negativo
 frente ao SQL Server/Oracle.

 Atenciosamente,


 Mozart Hasse


 ___
 pgbr-geral mailing list
 pgbr-geral@listas.postgresql.org.br
 https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral




-- 
William Leite Araújo
Analista de Banco de Dados - QualiConsult
___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral


Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres

2008-09-16 Por tôpico Mozart Hasse
Olá William,

 From:  William Leite Araújo [EMAIL PROTECTED]
 Subject: Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para
   Postgres
 
 Não há, no postgresql, trigger sobre a view. Use CREATE RULE. É
até
 melhor, porque uma regra pode ser aplicada a um SELECT também.
 

Eu cogitei essa opção, porém não sei se ela pode ser usada no meu caso
específico:

http://www.postgresql.org/docs/8.3/static/rules-triggers.html

If checks for valid values are required, and in the case of an invalid value
an error message should be generated, it must be done by a trigger.

O problema é que no meio das minhas triggers eu *tenho* validações que
podem gerar mensagens de erro, logo não sei se essa opção seria viável no
meu caso.

Outro inconveniente é que rules se aplicam sobre comandos inteiros, não
sobre atualizações registro a registro. Mudar a lógica da trigger/stored
procedure para trabalhar sobre o comando ao invés de trabalhar sobre
registros da tabela seria uma mudança extremamente radical, cujas
implicações no desempenho me preocupam bastante.

Vou ler a documentação e fazer alguns testes. Obrigado pela sugestão.


Mozart Hasse


___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral


Re: [pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres

2008-09-16 Por tôpico William Leite Araújo
2008/9/16 Mozart Hasse [EMAIL PROTECTED]

 Olá William,

 (...)
 Eu cogitei essa opção, porém não sei se ela pode ser usada no meu caso
 específico:

 http://www.postgresql.org/docs/8.3/static/rules-triggers.html

 If checks for valid values are required, and in the case of an invalid
 value
 an error message should be generated, it must be done by a trigger.

 O problema é que no meio das minhas triggers eu *tenho* validações que
 podem gerar mensagens de erro, logo não sei se essa opção seria viável no
 meu caso.


Bom, quando eu usei rules em views que eram simplesmente copias da
tabela original, as mesmas eram :

CREATE RULE [nome] AS ON INSERT TO [nome view] DO INSTEAD INSERT INTO
[tabela original](COALESCE(new.[campo1],
DEFAULT),COALESCE(new.[campo2],DEFAULT),...);

 E funcionavam certinho. Item para ocaso do update. Havia a facilidade
de um ID de registro nunca poder ser alterado. Assim ... DO INSTEAD UPDATE
[tabela original] SET [campo1] = new.[campo1] ... WHERE ID = new.[ID] sempre
funcionava.

 Na verdade, obviamente, eu tinha funções para criar as regras...



 Outro inconveniente é que rules se aplicam sobre comandos inteiros, não
 sobre atualizações registro a registro. Mudar a lógica da trigger/stored
 procedure para trabalhar sobre o comando ao invés de trabalhar sobre
 registros da tabela seria uma mudança extremamente radical, cujas
 implicações no desempenho me preocupam bastante.


  Bom, acho que o dito acima contesta essa afirmação. Não precisa
alterar seus triggers, desde que estejam na tabela original...

-- 
William Leite Araújo
Analista de Banco de Dados - QualiConsult
___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral


[pgbr-geral] Trigger mirabolante com View: de Oracle para Postgres

2008-09-15 Por tôpico Mozart Hasse
Olá,

Estou tentando converter um conjunto de triggers/stored procedures de Oracle 9
para Postgres 8.3.
Julgo ser necessário dar uma visão geral para dar idéia do tamanho da
encrenca:

A trigger tem a intenção de atualizar os valores de alguns campos (saldo
anterior e data inicial do próximo registro) no registro recém incluído, de
forma a deixar o registro incluído com valores coerentes com os registros
anteriores e posteriores, segundo um determinado critério de ordenação.
Visando proteger a integridade da tabela, é importantíssimo que os usuários
e a aplicação não consigam atualizar dados diretamente na tabela sem passar
pela trigger. Aliás, acho que o usuário/desenvolvedor ficará ainda mais
feliz se nem souber que existe uma trigger que corrige os valores para ele.

Devido à natureza recursiva dessa modelagem (eu preciso alterar dados do
próprio registro e em alguns casos dar mais de um UPDATE sobre o mesmo
registro), o Oracle não me permitia alterar o registro diretamente de dentro
da trigger. A solução adotada em Oracle foi a seguinte:

* Mover a tabela original para outro schema e protegê-la contra alterações
feitas diretamente pelos usuários ou pela aplicação;
* Criar uma view com o nome da tabela original;
* criar triggers do tipo INSTEAD OF UPDATE or INSERT or DELETE na View;
* dar os UPDATEs na tabela de fato ou na view, usando para isso SELECTs na
view quando necessário.

A solução, apesar de complexa, resolveu o problema em Oracle com ótimo
desempenho. Eu tenho uma versão igualmente eficiente para SQL Server, só que
preferi não usá-la como referência porque o SQL Server não se importa em
fazer alterações repetidas e recursivas sobre o mesmo registro. 

Falta fazer o mesmo em Postgres...

O problema é que eu não consigo achar meios de implementar a mesma
funcionalidade:

* se eu tento criar triggers com comandos UPDATE/DELETE diretamente sobre a
tabela, o Postgres dá aquele erro infame: 'ERROR: record new is not
assigned yet'. Suponho que o problema seja similar ao do Oracle. Estou certo?

* se eu tento usar a mesma solução adotada no Oracle, não consigo criar a
trigger sobre a view. Exemplo:

-- tabela original movida para outro schema
CREATE TABLE gestao.mvtoestq (.../* mais de 50 campos */ );

-- view que eu gostaria de atualizar pela aplicação
create or replace view public.mvtoestq as SELECT * FROM gestao.mvtoestq;

-- trigger function mirabolante que atualiza a view ou a tabela conforme uma
regra de negócio esdrúxula
create or replace FUNCTION finMvtoEstq() returns trigger as 
/* 250 linhas de código que chamam uma SP com mais 800 linhas cheias de
SELECTs monstruosos e UPDATEs mirabolantes */ 
... 
UPDATE public.mvtoestq SET...
...
UPDATE gestao.mvtoestq SET...
...
;

-- trigger sobre a view
CREATE TRIGGER tr_mvtoestq_ins
  instead of INSERT
  ON public.mvtoestq
  FOR EACH ROW
  EXECUTE PROCEDURE finmvtoestq();

Neste último comando o Postgres me retorna:

ERROR:  syntax error at or near instead
LINE 2:   instead of INSERT


Finalmente as perguntas: 
1. O que eu faço agora? 
2. Tem como contornar o problema sem precisar de uma View ? 
3. Tem algum jeito de implementar de maneira equivalente ao Oracle ? 
4. Tem algum outro jeito que funcione em Postgres ?
5. Alguém já passou por algo parecido ? Qual a solução adotada ?

Atualmente todos os comandos das triggers e stored procedures estão embutidos
no código da aplicação e são ativados somente quando ela usa Postgres.
Isso complica imensamente a manutenção, dificulta a depuração e aumenta
muito a chance de erros, além de dar ao usuário e ao desenvolvedor a chance
(raramente desperdiçada) de deixar a tabela com dados inconsistentes.

Grato pela atenção,


Mozart Hasse


___
pgbr-geral mailing list
pgbr-geral@listas.postgresql.org.br
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral