criar registro dinâmico

Discussão em 'Progress 4GL' iniciado por raffaell, Agosto 16, 2013.

  1. raffaell

    raffaell Sem Pontuação

    Estou desenvolvendo uma rotina única de insert no banco onde passaríamos a tabela e uma temp-table com os valores para gravação.

    Ex.:
    Run pi-insert(Input 'cliente',
    Input-output table tt-cliente).

    Procedure pi-insert:

    Def input param piTabela as char no-undo.
    Def input param table for tt-default.

    /* => Probema: a temp-table tt-default teria que ser criada dinamicamente com as caractersticas da temp-table envianda*/

    Create piTabela.
    Buffer-copy tt-default to piTabela.

    /* => Probema: O progress não permite a criação de um registro a partir do valor do parâmetro recebido nem o Buffer-copy da temp-table para a mesma*/

    End Procedure.

    alguem já desenvolveu alguma rotina desse tipo?
  2. Mokwa

    Mokwa Membro Participativo

    Da uma olhada nessa função, acho que soluciona seu primeiro problema.

    Código:
    DEFINE VARIABLE tth AS HANDLE NO-UNDO. 
    CREATE TEMP-TABLE tth.
    tth:ADD-FIELDS-FROM("Customer").
    Não entendi o problema 2, se puder explicar melhor talvez possa ajudar.
  3. allan

    allan Sem Pontuação

    Primeiramente obg pela resposta.

    Estamos trabalhando no conceito de aplicação distribuída, ou seja, no lado do usuário toda a manipulação dos dados é feita em temp-tables passando as mesmas por parâmetro para um programa externo que centraliza as manipulações no banco de dados.
    Todo processo é feito de forma estática, ou seja, criamos procedures internas de inserção, deleção, alteração e busca para cada tabela que precisamos dar manutenção.

    Ex.:

    exemplo1.p

    def temp-table tt-paciente like paciente
    field RowIdent as Rowid.

    Run SavePacienteRecord(input-output table tt-paciente,
    input 'novo',
    input tt-paciente.RowIdent).



    exemplo2.p

    PROCEDURE SavePacienteRecord :
    /*------------------------------------------------------------------------------
    Purpose:
    Parameters: <none>
    Notes:
    ------------------------------------------------------------------------------*/
    DEFINE INPUT-OUTPUT PARAMETER TABLE FOR tt-paciente.
    DEFINE INPUT PARAMETER pcMode AS CHARACTER NO-UNDO.
    DEFINE Input PARAMETER prRowIdent AS Rowid NO-UNDO.

    Find First tt-paciente
    Where tt-paciente.RowIdent = prRowIdent No-error.

    DO TRANSACTION:
    IF pcMode = "novo" THEN Do:
    Find Last Paciente Exclusive-lock No-error.
    If Avail Paciente Then
    Assign tt-paciente.codPaciente = Paciente.codPaciente + 1.
    Else
    Assign tt-paciente.codPaciente = 1.

    CREATE Paciente.

    End.

    ELSE
    FIND Paciente WHERE ROWID(Paciente) = tt-paciente.RowIdent
    EXCLUSIVE-LOCK NO-WAIT NO-ERROR.



    /* Do the following for both new and modified records */
    IF AVAILABLE Paciente THEN
    BUFFER-COPY tt-paciente EXCEPT RowIdent TO Paciente.
    ELSE
    IF LOCKED (Paciente) THEN
    RETURN "Registro bloqueado. Tente mais tarde.".
    ELSE
    RETURN "Registro já foi deletado!".
    END. /* Transaction */
    FIND CURRENT Paciente NO-LOCK. /* Remove the lock */
    BUFFER-COPY Paciente TO tt-paciente.
    Assign tt-paciente.rowIdent = ROWID(Paciente).

    RETURN.



    END PROCEDURE.

    gostariamos de criar uma procedure única para tratar cada manipulação
    por exemplo criar uma parocedure que a partir dos parâmetros de "nome-da-table" e "um registro da temp-table" possa realizar inserção em qualquer tabela do banco dinamicamente.
    ou uma sugestão de como ser feito essa implementação no progress.

    /* Um problema que tenho para usar essa procedure dinamicamente é que passo como parametro uma temp-table com o registro para ser manipulada, sendo assim a temp-table que é esperada como parâmetro tem que conter as mesmas caracteristicas da passada por parametro.
    O Segundo é que se passar o nome da tabela por parametro
    exemplo SavePacienteRecord(input 'Paciente').
    e recebe-la como um char
    def input param piTable as char no-undo.

    não consiguirei realizar comando de tabela no parâmetro
    ex.: find first piTable no-error.
    porque a table piTable não existe, mas sim o valor do parametro é o nome da tabela */
  4. Mokwa

    Mokwa Membro Participativo

    Eu usei nesse exemplo a tabela CLIENTE, se for alterar cuida de alterar o nome da Temp-Table também.

    Código:
    FUNCTION getNewID RETURNS DECIMAL
      ( INPUT pcNomeTabela AS CHARACTER ) :
    /*------------------------------------------------------------------------------
      Purpose:  
        Notes:  
    ------------------------------------------------------------------------------*/
    DEFINE VARIABLE hBuffer AS HANDLE NO-UNDO.
    
       CREATE BUFFER hBuffer FOR TABLE pcNomeTabela.
    
       hBuffer:FIND-LAST().
    
       IF hBuffer:AVAILABLE THEN
          RETURN hBuffer:BUFFER-FIELD(1):BUFFER-VALUE + 1.
    
      RETURN 1.   /* Function return value. */
    
    END FUNCTION.
    
    /* Lado do Cliente , onde ocorre a criacao do registro */
    
    DEFINE TEMP-TABLE tCliente NO-UNDO LIKE CLIENTE.
    
    DEFINE VARIABLE hBuffer AS HANDLE NO-UNDO.
    
    FIND LAST CLIENTE NO-LOCK NO-ERROR.
    
    CREATE tCliente.
    BUFFER-COPY CLIENTE TO tCliente.
    
    ASSIGN hBuffer = BUFFER tCliente:HANDLE.
    
    RUN 'ManipularRegistro' (INPUT 'Novo', INPUT hBuffer).
    
    IF RETURN-VALUE <> 'OK' THEN DO:
       MESSAGE RETURN-VALUE VIEW-AS ALERT-BOX ERROR BUTTONS OK.
    END.
    
    
    /* Processo executando no servidor */
    
    PROCEDURE 'ManipularRegistro':
    
       DEFINE INPUT  PARAMETER pcOperacao AS CHARACTER  NO-UNDO.
       DEFINE INPUT  PARAMETER phBuffer   AS HANDLE     NO-UNDO.
       DEFINE VARIABLE         hTabela    AS HANDLE     NO-UNDO.
       DEFINE VARIABLE         cNomeTab   AS CHARACTER  NO-UNDO.
    
       phBuffer:FIND-FIRST().
    
       /* Consistencias Gerais */
       IF NOT VALID-HANDLE(phBuffer) THEN DO:
          RETURN 'Condicao de Erro'.
       END.
    
       /* Aqui voces teriam que decidir um convencao para o nome da tabela 
          parti do principio que o nome da temp-table tera que ser o nome 
          da tabela com um T na frente (e.i.: Tabela: Fornecedor, Temp-Table tFornecedor */
    
       ASSIGN cNomeTab = SUBSTRING(phBuffer:NAME, 2).
    
       CREATE BUFFER hTabela FOR TABLE cNomeTab.
    
       CASE pcOperacao:
          WHEN 'Novo' THEN DO:
    
             /* Consistencias da Operacao */
             IF NOT phBuffer:AVAILABLE THEN DO:
                RETURN 'Condicao de Erro'.
             END.
    
             BLOCO_ATUALIZA:
             DO TRANSACTION ON ERROR UNDO BLOCO_ATUALIZA, RETURN 'Erro ao Criar Novo Registro.':
             
                hTabela:BUFFER-CREATE.
    
                hTabela:BUFFER-COPY(phBuffer, hTabela:BUFFER-FIELD(1):NAME).
       
                /* Aqui outra convencao, para pegar a chave do registro 
                   Decidi que o primerio campo da tabela sempre sera a chave do registro */
       
                hTabela:BUFFER-FIELD(1):BUFFER-VALUE = getNewID(INPUT cNomeTab).
       
                hTabela:BUFFER-RELEASE.
             END.
          END.
       END.
    
       RETURN 'OK'.
    
    END PROCEDURE.
    
  5. rafael.andrade

    rafael.andrade Membro Master Moderador Equipe de Suporte

    Porque você não passa a TEMP-TABLE inteira como parâmetro?

    Vou te mostrar um exemplo:

    1. Primeiro você cria uma include (.i) com a definição padrão da TEMP-TABLE, tipo:
    DEF TEMP-TABLE teste
    FIELD nome AS CHAR
    FIELD idade AS INTEGER.

    2. Tanto no programa Pai como no programa Filho, você chama essa include no DEFINITIONS:
    {pasta\definitions01.i}

    3. No programa Pai (ex.: Pai.w ou .p) você executa o filho (filho.w ou .p) passando a temp-table já preenchida.
    RUN filho.w(INPUT TABLE teste).

    4. Dentro do programa Filho, você coloca a chamada da include no definitions (conforme passo 2) e, logo após, cria a definição de parametro.
    DEF INPUT PARAMETER TABLE FOR teste.

    Obs.: Se você precisar mexer na temp-table atualizada após o programa filho usar, na definição de parâmetro você coloca INPUT-OUTPUT e no RUN também INPUT-OUTPUT.

    Pronto, agora você pode utilizar a tabela a vontade do outro lado, no programa filho.

    Espero ter ajudado.

    Att,

    Rafael

Compartilhe esta Página