Rotina de Auditoria para SGBD

Forum sobre SQL.

Moderador: Moderadores

Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Rotina de Auditoria para SGBD

Mensagem por asimoes »

Pessoal,

Estou migrando para um SGDB, escolhi o MariaDb, no momento usando o ADS da SYBASE como ponte na construção das query´s, tenho uma função de auditora de dados no DBF, onde comparo os campos do registro atual com o modificado, como fazer isso agora ?
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Rotina de Auditoria para SGBD

Mensagem por JoséQuintas »

Sugestão:

Toda tabela tem uma chave.
cria uma rotina pra pegar o registro e comparar.

Uma primeira rotina salva num array
Uma segunda rotina comparara esse array com o array atual.

Registro:Salva( "tabela", "chave" )

atualiza

Registro:Compara( "tabela", "chave" )
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

Rotina de Auditoria para SGBD

Mensagem por alxsts »

Olá!

Use triggers...
[]´s
Alexandre Santos (AlxSts)
Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Rotina de Auditoria para SGBD

Mensagem por asimoes »

alxsts escreveu:Olá!

Use triggers...
Ainda não migrei para o MariaDb, estou na fase de troca de sintaxe paa acessar o dbf, via sql

Quintas tens algum exemplo ?
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Rotina de Auditoria para SGBD

Mensagem por asimoes »

JoséQuintas escreveu:Sugestão:

Toda tabela tem uma chave.
cria uma rotina pra pegar o registro e comparar.

Uma primeira rotina salva num array
Uma segunda rotina comparara esse array com o array atual.

Registro:Salva( "tabela", "chave" )

atualiza

Registro:Compara( "tabela", "chave" )
Tenho uma rotina que é uma grid onde e o usuário pode excluir qq linha dessa grid que persiste no dbf, antes de auditar faço um set deleted off pra poder pegar o registro deletado, depois faço set deleted on, acontece que com o ads não tem isso, não funciona o set deleted off pra poder pegar o deleted do dbf
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Rotina de Auditoria para SGBD

Mensagem por JoséQuintas »

ainda estou adaptando, mas de um modo geral é salvar no array.

Código: Selecionar todos

CREATE CLASS ADORecValueClass

   VAR aValues

   METHOD New( cnMySql )
   METHOD WriteLog( cTable, cKeyName, xKeyValue )

   ENDCLASS

METHOD New( cnMySql ) CLASS ADORecValueClass

   LOCAL nCont

   ::aValues := {}
   IF cnMySql != NIL
      WITH OBJECT cnMySql
         FOR nCont = 1 TO :FCount()
            AAdd( ::aValues, :String( nCont - 1 ) )
         NEXT
      ENDWITH
   ENDIF

   RETURN SELF

METHOD WriteLog( cTable, cKeyName, xKeyValue ) CLASS ADORecValueClass

   LOCAL nCont, cnMySql := ADOClass():New( AppConexao() )

   IF AppConexao() == NIL
      RETURN NIL
   ENDIF
   WITH OBJECT cnMySql
      :cSql := "SELECT * FROM " + cTable + " WHERE " + cKeyName + " = " + NumberSql( xKeyValue )
      :Execute()
      IF ! :Eof()
         FOR nCont = 1 TO :FCount()
            IF ! "INFINC" $ :FName( nCont - 1 ) .AND. ! "INFALT" $ :FName( nCont - 1 ) ;
               .AND. ! ::aValues[ nCont ] == :String( nCont - 1 )
               GravaOcorrencia( cTable, StrZero( xKeyValue, 9 ), "ALTERADO " + :FName( nCont - 1 ) + ;
                  " de " + Transform( ::aValues[ nCont ], "" ) + ;
                  " para " + :String( nCont - 1 ) )
            ENDIF
         NEXT
      ENDIF
      :CloseRecordset()
   ENDWITH

   RETURN NIL

   // Alterado pra usar com MySQL a partir de DBF

CREATE CLASS DBFRecValueClass

   VAR  aValues

   METHOD WriteLog( xTable, xKey )
   METHOD Init()

   ENDCLASS

METHOD Init() CLASS DBFRecValueClass

   LOCAL nCont

   ::aValues := {}
   FOR nCont = 1 TO FCount()
      Aadd( ::aValues, FieldGet( nCont ) )
   NEXT

   RETURN NIL

METHOD WriteLog( xTable, xKey ) CLASS DBFRecValueClass

   LOCAL cAlias, cCodigo, nCont, cTexto

   IF ! xTable == NIL .AND. ! xKey == NIL
      FOR nCont = 1 TO FCount()
         cTexto := ""
         IF ::aValues[ nCont ] != FieldGet( nCont ) .AND. ! "INFINC" $ FieldName( nCont ) .AND. ! "INFALT" $ FieldName( nCont )
            cTexto += FieldName( nCont ) + " DE " + Trim( Transform( ::aValues[ nCont ], "" ) )
            cTexto += " PARA " + Trim( Transform( FieldGet( nCont ), "" ) )
            GravaOcorrencia( Upper( xTable ), xKey, cTexto )
         ENDIF
      NEXT
      RETURN NIL
   ENDIF

   cAlias := Lower( Alias() )
   DO CASE
   CASE cAlias == "jpcadastro" ; cCodigo := jpcadastro->idCadastro
   CASE cAlias == "jpfinan"    ; cCodigo := jpfinan->idFinan
   CASE cAlias == "jpitem"     ; cCodigo := jpitem->idProduto
   CASE cAlias == "jppedido"   ; cCodigo := jppedido->idPedido
   OTHERWISE
      cCodigo := ""
   ENDCASE
   IF Empty( cCodigo )
      RETURN NIL
   ENDIF
   FOR nCont = 1 TO FCount()
      cTexto := ""
      IF ::aValues[ nCont ] != FieldGet( nCont ) .AND. ! "INFINC" $ FieldName( nCont ) .AND. ! "INFALT" $ FieldName( nCont )
         cTexto += FieldName( nCont ) + " DE " + Trim( Transform( ::aValues[ nCont ], "" ) )
      ENDIF
      IF ! Empty( cTexto )
         GravaOcorrencia( Upper( Alias() ), cCodigo , cTexto )
      ENDIF
   NEXT

   RETURN NIL
Tenho em cada registro o INFINC e INFALT que é data de inclusão/alteração, então não comparo no log, senão sempre iria gravar.
Mas é como eu falei: cria um array antes, e compara com o array depois.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Rotina de Auditoria para SGBD

Mensagem por JoséQuintas »

Em DBF:

oRec := DBFRecValuesClass():New()
REPLACE .....
oRec:WriteLog( Alias(), chave )

No log vai registrar a tabela, a chave, e o que mudou.

Em ADO... aproveito o SELECT * que pega o registro atual... e passo a tabela/chave para a rotina buscar no MySQL depois.
Pensando em usar tabela/chave nos dois casos.

Uso isso também pra ter as "ocorrências" individuais.
Por exemplo: vai lá no cadastro de clientes número 10, e vê o histórico de tudo que foi alterado nele, só precisa da tabela e chave pra isso.

No log geral vê tudo.
No log do cliente, só vê o que tá como "cliente", código "10"
Simples e prático.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Rotina de Auditoria para SGBD

Mensagem por JoséQuintas »

asimoes escreveu:acontece que com o ads não tem isso, não funciona o set deleted off pra poder pegar o deleted do dbf
Até tem, mas não faço idéia de como faria o SELECT para os deletados.
Isso fica na string de conexão, e poderia ter uma conexão para os deletados.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Rotina de Auditoria para SGBD

Mensagem por asimoes »

JoséQuintas escreveu:Até tem, mas não faço idéia de como faria o SELECT para os deletados.
Isso fica na string de conexão, e poderia ter uma conexão para os deletados.
No MaySql, Oracle ou MariaDb, o delete from table, não tem como ver, o registro é seguido de um "pack" se errou ferrou!, por isso essas coisas tem que estar dentro de um controle de transação begintrans(), CommitTrans() e RollBackTrans() o driver OleDb da Ads não tem isso.
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

Rotina de Auditoria para SGBD

Mensagem por alxsts »

Olá!
asimoes escreveu:No MaySql, Oracle ou MariaDb, o delete from table, não tem como ver, o registro é seguido de um "pack" se errou ferrou!
alxsts escreveu:Use triggers...
Toda vez que um trigger é disparado, tem-se acesso à situação atual do registro e a situação futura (imagens OLD e NEW, também conhecidos como "before image" e "after image"). Um trigger pode ser disparado antes ou depois de um INSERT, UPDATE ou DELETE. É só tratar a situação conforme a necessidade.

What is a Trigger? (ADS)

Writing Triggers in SQL (ADS)

Trigger Overview MariaDB
[]´s
Alexandre Santos (AlxSts)
Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Rotina de Auditoria para SGBD

Mensagem por asimoes »

Não faço a minima ideia como fazer uso de trigger do ads
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Responder