Passagem parametro campo include

Discussão em 'Progress 4GL' iniciado por sandrammss, Julho 27, 2012.

  1. sandrammss

    sandrammss Membro Participativo

    Bom dia,

    Estou desenvolvendo um programa para retornar o campo e o conteúdo de uma tabela que foram alterados (tipo algo que existe no audit trail).
    Estou guardando em uma tabela específica o valor do campo e o conteúdo dos mesmos.
    A dificuldade que estou encontrando é como jogar esta informacao que está na minha tabela especifica para a tabela de origem.
    Exemplo:

    Criei uma trigger de write na tabela emitente, e toda fez que algum campo é alterado, é gravado na tabela especifica o campo e o valor do mesmo (valor anterior e atual).

    es-tab-generica.cod-emitente = emitente.cod-emitente
    es-tab-generica.campo = "nome-emit"
    es-tab-generica.valor-new = b-emitente.nome-emit
    es-tab-generica.valor-old = b-old-emitente.nome-emit.

    Até ai tudo ok, o que preciso está abaixo:

    Find first emitente
    where emitente.cod-emitente = es-tab-generica.cod-emitente no-lock no-error.
    if avail emitente then

    assign c-campo = es-tab-generica.campo
    emitente.c-campo = es-tab-generica.valor-new.

    O problema está aqui: emitente.c-campo (fiz como está abaixo, mas o problema é que a tabela emitente tem um número muito grande de campos e precisaria de uma lógica mais inteligente para nao ter que repetir dentro do case o nome de cada campo.

    CASE c-campo:

    WHEN "nome-emit":U THEN DO:
    {upc/w-emitente.i b-emitente.nome-emit b-old-emitente.nome-emit nome-emit }
    END.
    end.
  2. jaozi_nho

    jaozi_nho Membro Participativo

    Não entendi muito bem a duvida, mas vou tentar ajudar...

    Se você não quer repetir vários when dentro de um case, procure achar um padrão e criar uma include para isso, nesse seu caso encontrei um, vou dar um exemplo:

    Conteudo da Include:

    Código:
    {upc/w-emitente.i b-emitente.{1} b-old-emitente.{1} {1} }
    Conteudo do codigo, substituindo todo o case e todos os when por:

    Código:
    {upc/w-emitente_include.i c-campo}
    Acho que isso funciona, abraço
  3. sandrammss

    sandrammss Membro Participativo

    Para ficar mais claro, preciso de algo conforme o exemplo abaixo:


    FOR EACH es-aprov-emitente.

    {pdp/teste.i es-aprov-emitente.campo } /* onde o es-aprov-emitente.campo contem o nome de um campo da tabela emitente, como por exemplo Nome-emit)

    END.

    conteudo da Include teste.i abaixo:

    FIND FIRST emitente NO-LOCK NO-ERROR.
    IF AVAIL emitente THEN
    DISP emitente.{1}. /*aqui está dando erro, pois o progress nao entende o .{1} , deveria ser emitente.nome-emit, conforme o conteúdo armazenado em es-aprov-emitente.campo */
  4. eduardo.leite

    eduardo.leite Equipe de Suporte Moderador Equipe de Suporte

    Caro colega,

    O que você deseja no progress é praticamento inviável de ser feito, se usar o processo da include, quando da compilação para ser executado a compilação grava internamente na rotina *.p o conteudo da rotina *.i, substituindo as constantes (exemplo {1}) pelo valor passado, neste caso você não está passando "nome-abrev" mas "es-aprov-emitente.campo".

    Uma outra maneira que poderia ser usada seria criar uma rotina *.p em momento de execução e disparar ela, por exemplo, a cada item lido na tabela "es-aprov-emitente" você criaria um arquivo com os comandos que deseja e após a criação iria disparar, porém este também não seria viável, pois o progress dos usuário teria que ter permissão para compilar, ou seja, executar rotina sem ter o *.r. O cliente não executa rotinas *.p e somente rotinas *.r.

    Sendo assim, a unica maneira mesmo, que é o que o AUDITRAIL faz, é gerar as rotinas com os nomes que deseja controlar, lembra que o AUDITRAL você monta selecionando os campos e depois compila as rotinas com os novos campos.

    Para evitar que você tenha que escrever o código várias vezes ou usar o CTRL-C e CTRL-V e alterar os campos, segue abaixo uma lógica que monta para você a lógica com os dados. Mas lembre-se, sempre que tiver novos campos ou excluidos campos deverá ser ajustado a lógica gerado.

    Código:
    
    def var c-campo     as character    no-undo.
    
    output to c:\temp\lista-logica.txt.
    
    put unformatted 
        "case c-campo:" skip(1).
    
    for each mgadm._File
       where mgadm._File._File-Name = "emitente" no-lock,
        each mgadm._Field of mgadm._File no-lock:
    
        put unformatted
            '    when "' mgadm._Field._Field-Name '" then ' skip 
            '        assign es-tab-generica.cod-emitente = emitente.cod-emitente' skip 
            '               es-tab-generica.campo        = "' mgadm._Field._Field-Name '"' skip
            '               es-tab-generica.valor-new    = b-emitente.' mgadm._Field._Field-Name skip
            '               es-tab-generica.valor-old    = b-old-emitente.' mgadm._Field._Field-Name '.' skip(1).
    
    end.
    
    put unformatted
        "end case." skip.
    
    output close.
    
    Exemplo da rotina gerada

    Arquivos Anexados:

  5. rhemati

    rhemati Membro Participativo

    Sandra, bom dia.

    Esta opção abaixo deve te ajudar. Só não padronizei conforme o seu exemplo. Terá que fazer testes.

    OBrigado.

    Código:
    /* preprocessador.i */
    &scoped-define p-campos {1} {2}
    
    MESSAGE '{&p-campos}' {&p-campos}
        VIEW-AS ALERT-BOX INFO BUTTONS OK.
    
    for each item no-lock
        where item.it-codigo = '613.1':
        display {&p-campos}.
    end.
    
    Código:
    /* preprocessador.p */
    
    def var c-it-codigo as char format 'x(20)' init 'item.it-codigo'.
    def var c-desc-item as char format 'x(20)' init 'item.desc-item'.
    
    {preprocessador.i  c-it-codigo c-desc-item }
    
    Outro Exemplo:
    Código:
    /* preprocessador.-hcm.i */
    
    &scoped-define p-campos {3} {4}
    
    MESSAGE '{&p-campos}' {&p-campos}
        VIEW-AS ALERT-BOX INFO BUTTONS OK.
    
    for each {1}.{2} no-lock
        :
        display {1}.{2}.{3}
                {1}.{2}.{4}
                .
    end.
    
    Código:
    /* Arquvo Preprocessador-hcm.p */
    def var c-nom_pessoa_fisic    as char format 'x(40)'    init 'nom_pessoa_fisic'.
    def var c-cdn_funcionario     as char format 'x(12)'    init 'cdn_funcionario'.
    
    
    def var c-banco     as char init 'hr209'.
    def var c-tabela    as char init 'funcionario'.
    
    assign  c-banco     =   'hr209'
            c-tabela    =   'funcionario'.
    
    run pre-hcm.p  c-banco c-tabela c-nom_pessoa_fisic c-cdn_funcionario.
    
    Código:
    /* Arquvo pre-hcm.p */
    
    for each {1}.{2} no-lock
        :
        display {1}.{2}.{3}
                {1}.{2}.{4}
                .
    end.
    
    dudabrito curtiu isso.
  6. jalegria

    jalegria Membro Participativo

    Bom dia a todos...
    Enfrentei o mesmo problema em minha empresa há alguns anos.

    Aqui tinhamos n triggers diferentes para um monte de tabelas sem padrão nenhum.
    E para cada tabela tinhamos que pegar campo a campo e montar "na unha".

    Criei um "esquema" para gerar log de alterações (triggers de write) sem ter o trabalho de lembrar nomes de campos, etc...
    De outra maneira fica inviavel (trabalhoso) para um sistema com uma qtde maior de tabelas.
    Espero que ajude...

    Esta include será colocada no .p da trigger de write da tabela em questão.
    A variavel muser se aplica ao meu ambiente, serve para apontar se a alteração foi feita por algum usuario.
    Cada um ajusta às suas necessidades.

    Código:
    /*==============================================================================
     Programa...: trig-write.i
     Descricao..: Include para cricao de log de write em tabelas
     Autor......: Jefferson Ferreira Alegria
     Data.......: 12/01/2010
     Obs........: 
    ==============================================================================*/
    
    trigger procedure for write of {1} old buffer old-{1}.
    
    def new global shared var muser like cadusu.usr-codusu.
    
    FUNCTION Log-Texto RETURNS CHAR():
    
      def var bf as widget-handle extent 2.
      def var campos as char.
      def var texto  as char.
      
      if new {1}
      then texto = 'INCLUIDO'.
      else do:
        bf[1] = buffer old-{1}:handle.
        bf[2] = buffer {1}:handle.
    
        buffer-compare old-{1} to {1} save result in campos.
        run trig-write.p(bf[1], bf[2], campos, output texto).
        
        texto = 'ALTERADO' + chr(10) + chr(10) + texto.
      end.
      
      return texto.
      
    END FUNCTION.
    
    Este programa é utilizado na include acima.
    Ele verifica quais campos da tabela foram alterados.
    Notem que não tem nomes de tabelas, que seria o maior problema no Progress, são utilizados buffers.
    Eu uso o label, se não der uso o column-label, além do nome do campo. Cada um pode ajustar ao seu gosto tb.

    Código:
    /*==============================================================================
     Programa...: trig-write.p
     Descricao..: Rotina para cricao do texto de log de write em tabelas
     Autor......: Jefferson Ferreira Alegria
     Data.......: 12/01/2010
     Obs........: 
    ==============================================================================*/
    
    def input  param bf-old as widget.
    def input  param bf-new as widget.
    def input  param campos as char.
    def output param texto  as char.
    
    def var i as int.
    def var f as widget-handle extent 2.
    
    
    if bf-old:buffer-compare(bf-new) then return.
    
    do i = 1 to bf-old:num-fields:
    
      f[1] = bf-old:buffer-field(i).
      if lookup(f[1]:name, campos) = 0 or lookup(f[1]:name, campos) = ? then next.
      
      f[2] = bf-new:buffer-field(i).
      
      
      texto = texto + 'Campo: ' +
              trim(caps(if f[1]:label <> ? and f[1]:label > ' '
                        then f[1]:label + ' [' + f[1]:name + ']'
                        else if f[1]:column-label <> ? and f[1]:column-label > ' '
                             then f[1]:column-label + ' [' + f[1]:name + ']'
                             else f[1]:name)) + chr(10) +
             'De...: ' + f[1]:string-value + chr(10) +
             'Para.: ' + f[2]:string-value + chr(10) + chr(10).
    end.
    
    texto = trim(texto).
    
    E abaixo seria um modelo da trigger da(s) tabela(s).
    Aqui tb cada um pode variar.

    O que vale é a função "Log-Texto()" que monta o texto com os campos alterados com um antes e depois.
    Pode ser feito desta forma, ou tb ao inves de gerar um texto, poderia ser gravado em uma tabela campo a campo.

    Preferi fazer assim para gerar somente um registro na tabela de log para cada alteração, e montei um programa para ver o log de qualquer tabela.
    Basta exibir o texto em um campo editor.

    Código:
    {trig-write.i nomedatabela}
    
    create tabelalog.
    assign tabelalog.tabela  = "nomedatabela"
           tabelalog.data    = today
           tabelalog.hora    = time
           tabelalog.usuario = muser
           etc.
    
    tabelalog.texto = Log-Texto().
    
    Fiz nos mesmos moldes uma include para trigger de delete, é quase igual, somente exibo os valores de todos os campos no momento da exclusão.
    rbaselio curtiu isso.

Compartilhe esta Página