Clipper On Line • Ver Tópico - DBF para MySQL com gravação dupla

DBF para MySQL com gravação dupla

Aqui você poderá oferecer suas Contribuições, Dicas e Tutoriais (Texto ou Vídeo) que sejam de interesse de todos.

Moderador: Moderadores

 

DBF para MySQL com gravação dupla

Mensagempor JoséQuintas » 13 Mai 2020 12:56

Vou colocar aqui como faço minha conversão de DBF pra MySQL, utilizando essa técnica que fiz com gravação dupla.
Uso minha classe de cadastros, mas tudo bem, seria no mesmo estilo caso ela não existisse.
Usar mais a parte teórica, porque a prática está relacionada com meu uso, então o fonte pode não servir pra outras situações.

Primeiro uma prévia das rotinas padrão, no meu caso dentro da classe:

- primeiro - GO TO TOP
- último - GO TO BOTTOM
- anterior - SKIP -1
- próximo - SKIP
- específico - é um GET no código pra posicionar
- tela de dados - é um SAY geral ou um GET geral

Essa parte acima é padrão, por isso agrupei uma classe.
Ao usar para um cadastro, faço herança, e substituo os métodos específico e tela dados, porque estes dois são diferentes pra cada cadastro.
No caso de vocês, que não tem classe, tudo bem, as rotinas acima seriam rotinas fixas, que são copiadas de um fonte para o outro.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

DBF para MySQL com gravação dupla

Mensagempor JoséQuintas » 13 Mai 2020 13:05

Primeiro passo:

Como fazer no mysql o equivalente às rotinas padrão de DBF?

A forma que encontrei foi me basear no código, a partir do código atual (se precisar), localizar no arquivo.

Primeiro:
no DBF tá indexado, é GOTO TOP
Equivale ao primeiro código, de uma lista em ordem crescente.
SELECT CODIGO FROM CLIENTES ORDER BY CODIGO LIMIT 1

Último:
Idem, GOTO BOTTOM
Equivale ao último código, de uma lista em ordem decrescente.
SELECT CODIGO FROM CLIENTES ORDER BY CODIGO DESC LIMIT 1

Seguinte:
Idem, SKIP
Equivale ao menor código maior que o atual.
Pegando os códigos maiores que o atual, em ordem crescente, é o primeiro da lista.
SELECT CODIGO FROM CLIENTES WHERE CODIGO > CodigoAtual ORDER BY CODIGO LIMIT 1

Anterior:
SKIP -1
Equivale ao primeiro código MENOR que o atual.
Pegando os códigos menores que o atual, em ordem decrescente, é o primeiro da lista.
SELECT CODIGO FROM CLIENTES WHERE CODIGO < CodigoAtual ORDER BY CODIGO DESC LIMIT 1

Pronto, parte padrão resolvida.
Já tem rotinas pra substituição, apenas está resolvido, não que já coloque em uso.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

DBF para MySQL com gravação dupla

Mensagempor JoséQuintas » 13 Mai 2020 13:13

Alterando o fonte propriamente dito:

As rotinas anteriores, por enquanto são anotações apenas.

A primeira parte na conversão é atualizar DBF e MySQL ao mesmo tempo.
Então... aonde tem o REPLACE no DBF, acrescento o UPDATE para o MySQL.
E aonde tem o APPEND, acrescento o INSERT para o MySQL.

A partir daqui, gravação dupla, DBF e MySQL estão atualizados.
Mesmo esquema do DBF apenas atualiza o MySQL.

A partir daqui, poderia atualizar relatórios e outras pesquisas !!!
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

DBF para MySQL com gravação dupla

Mensagempor JoséQuintas » 13 Mai 2020 13:17

Confirmado que DBF e MySQL estão sincronizados, mesma gravação nos dois...
Todo aplicativo pode pesquisar no MySQL ao invés do DBF.
browses, relatórios, etc. todos podem usar MySQL.

O primeiro da lista são os browses, pra ganho de velocidade.
Se a alteração foi suficiente, também relatórios e outras pesquisas.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

DBF para MySQL com gravação dupla

Mensagempor JoséQuintas » 13 Mai 2020 13:25

O próximo passo é tornar o MySQL como principal.
Aqui entram aquelas rotinas que foram anotadas.
Num primeiro momento, o SEEK nos DBFs vai posicionar no registro, após pesquisar no MySQL.
Desta forma, o fonte vai ter a informação do DBF ou do MySQL, mas pode aguardar pra ser alterado pra MySQL depois.
Se o fonte pega do DBF funciona, e se pega do MySQL funciona, apenas o MySQL começa a ser o principal, o ponto de partida para prosseguir.

Neste ponto, posso usar o campo incremental do MySQL pra fornecer o próximo código disponível.
E uso esse código pra salvar tanto no MySQL como no DBF.

Neste momento, o aplicativo passa a ter a vantagem do campo incremental único, enquanto continua salvando em DBF e MySQL.
Qualquer pesquisa/relatório podendo ser atualizado pra MySQL, sem depender do DBF.
Dá até pra usar DBF e MySQL ao mesmo tempo, até se acostumar a buscar toda informação somente no SQL.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

DBF para MySQL com gravação dupla

Mensagempor JoséQuintas » 13 Mai 2020 14:11

Depois disso, trata-se apenas de não usar mais o DBF.

Se alterar só o arquivo de clientes, não vai ser suficiente pra transformar um relatório de notas fiscais por cliente totalmente pra MySQL, mas talvez possa alterar o relatório de clientes.
Se alterar só o arquivo de notas fiscais, idem, mas talvez possa pelo menos buscar as notas fiscais, e pesquisar os clientes via DBF.
Se alterar os dois, pode fazer totalmente em MySQL.

Justamente por isso mudei minha conversão:
Comecei alterando um arquivo por vez pra MySQL, mas notei que se fossem vários, teria mais vantagem.

Neste ponto dá pra comparar SQLMIX com ADO, ou esse esquema de alteração:

Vantagem do SQLMIX sobre ADO: não alterar o fonte na parte de leitura, mas precisa alterar gravação igual ADO, pra comandos SQL.
Vantagem do SQL: consultas trazendo somente o que interessa, o que só é obtido com alteração de fonte, caso contrário fica pior do que com DBF.
Conclusão: a vantagem do SQLMIX é.... aproveitar fonte que vai ser jogado fora, ganhar tempo de conversão deixando mais lento do que deveria ser.
E o pior: pode dar a falsa impressão de que SQL é demorado, porque o fonte não foi feito pra SQL e sim pra DBF.

Por outro lado, é lógico, depende do programador.
Esse mesmo esquema que usei pra ADO poderia ser usado pra SQLMIX.
Do mesmo jeito que estou alterando relatórios pra tirar proveito do MySQL usando ADO, também poderia ser usado no SQLMIX.

Acho que o maior problema do SQLMIX NÃO é o SQLMIX, mas o fato dele dar a impressão ao programador que vai continuar trabalhando igual DBF.

SQL é relativamente simples, mas o programador precisa entender que SQL é SQL, e DBF é DBF.
E ficar usando SQL igual DBF não é uma boa maneira do programador entender isso.

Não sei se seria exagero dizer o seguinte:
SQLMIX é ótimo, pra quem já está acostumado com SQL, e não pra principiante que está começando a entrar no mundo SQL.
Quem já está acostumado com SQL, sabe muito bem a diferença, mas quem está começando.... vai entender cada vez menos.

o ADO deixa mais claro isso, mas nem sei se mesmo assim o pessoal entendeu.
Basicamente são duas variáveis:
uma variável é a conexão, é o elo de ligação entre o programa e o servidor

oConexao := win_OleCreateObject( "ADODB.Connection" )

Outra variável é a resposta do servidor, contendo qualquer coisa.
É enviar o comando e obtém-se a resposta em uma variável.

oTemporario := oConexao:Execute( "comando sql" )

Podemos fazer consultas diferentes, em variáveis diferentes, mas isso é uma variável contendo a resposta do servidor em formato ADO.
É o Windows que faz isso, talvez seja array, talvez seja arquivo temporário, não faço idéia, apenas é fazer uso disso.

Com certeza o SQLMIX faz algo parecido, mas na maior parte do tempo é um SELECT *, trás tudo, quando nem precisamos de tudo.
Mas é lógico, como eu disse, depende do programador ENTENDER do que se trata SQL, e impedir que isso seja feito.
O fato do SQLMIX trazer em formato DBF, não significa que isso virou DBF.

Até mesmo hbmysql... qual a vantagem de trazer o processamento ao aplicativo, se o Windows faz isso sozinho e mais rápido?

De qualquer forma, só existe ADO no WINDOWS.
Mas nada impede do programador usar ADO pra ENTENDER SQL, e só depois adotar o SQLMIX da forma correta, ou pra usar no Linux, ou pra permitir usar os browses de libs gráficas que só atendem DBF ou Array.

Na prática o ADO é igual uma RDD, com muito mais recursos do que comandos SQL, mas.... podem entrar particularidades do ADO.

Como comparação:

O jeito que eu mostro ADO aqui no fórum, seria o mesmo do que usar SQLMIX apenas com o Execute().

E se o ADO morrer?

- executar comandos
- executar comandos trazendo retorno

Se uma LIB fizer isso, o que todas fazem, ninguém está nem preso ao ADO e nem ao Windows, pode trocar quando quiser.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

DBF para MySQL com gravação dupla

Mensagempor JoséQuintas » 13 Mai 2020 15:25

Tinha esquecido de alterar o cadastro pra MySQL.... começando a alterar agora.
Vejam esta rotina:

METHOD Email() CLASS JPCADASTROClass

   LOCAL cAssunto, cTxt, mIdCadastro

   mIdCadastro := ::axKeyValue[ 1 ]
   IF mIdCadastro == 0
      MsgWarning( "Selecione primeiro o cliente" )
      RETURN NIL
   ENDIF
   Encontra( StrZero( mIdCadastro, 6 ), "JPCADASTRO", "NUMLAN" )
   IF Empty( jpcadastro->cdEmail )
      MsgWarning( "Cliente não contém endereço de email" )
      RETURN NIL
   ENDIF
   IF ! MsgYesNo( "Confirme o envio de email" )
      RETURN NIL
   ENDIF
   cAssunto = "Cad." + Str( mIdCadastro, 6 ) +  " " + jpcadastro->cdNome

   cTxt := []
   cTxt += [<html font size="2">]
   cTxt += [<table width="95%">]
   cTxt += [<tr><td></td></tr>]
   cTxt += [<tr><td align="CENTER">FICHA DE CADASTRO</td></tr>]
   cTxt += [<tr><td></td></tr>]
   cTxt += [<tr><td>CÓDIGO: ] + jpcadastro->idCadastro + [</td></tr>]
   cTxt += [<tr><td>NOME: ] + jpcadastro->cdNome +  [</td></tr>]
   cTxt += [<tr><td>ENDEREÇO: ] + jpcadastro->cdEndereco + [</td></tr>]
   cTxt += [<tr><td>BAIRRO: ] + jpcadastro->cdBairro + [</td></tr>]
   cTxt += [<tr><td>CIDADE: ] + jpcadastro->cdCidade + [</td></tr>]
   cTxt += [<tr><td>UF: ] + jpcadastro->cdUf +   [</td></tr>]
   cTxt += [<tr><td>CEP: ] + jpcadastro->cdCep + [</td></tr>]
   cTxt += [<tr><td>CPF-CNPJ: ] + jpcadastro->cdCnpj + [</td></tr>]
   cTxt += [<tr><td>INSCR.ESTADUAL: ] + jpcadastro->cdInsEst +   [</td></tr>]
   cTxt += [<tr><td>OUTRO DOCTO: ] + jpcadastro->cdOutDoc +  [</td></tr>]
   cTxt += [<tr><td>EMAIL: ] + jpcadastro->cdEmail +  [</td></tr>]
   cTxt += [<tr><td></td></tr>]
   cTxt += [</table></font></html>]
   EnviaEmail( { Trim( jpcadastro->cdEmail ) },, cAssunto, cTxt )

   RETURN NIL


Ao alterar a rotina principal pra MySQL, o código chave é este:
mIdCadastro := ::axKeyValue[ 1 ]

Esta parte posiciona o DBF:
Encontra( StrZero( mIdCadastro, 6 ), "jpcadastro", "numlan" )

e a rotina segue usando o DBF.
Ou seja... mesmo passando a usar MySQL na rotina principal, ainda funciona buscar informações do DBF pra esta rotina.

Agora basta alterar esta rotina pra usar informações do MySQL e não do DBF.

O mais importante:
Funcionava antes com DBF, instalado no cliente.
Funciona agora alterado parcialmente pra MySQL, se eu instalar AGORA no cliente continua funcionando.
Vai funcionar depois de alterar esta rotina pra MySQL, e se instalar no cliente depois, no cliente continua funcionando.

Entenderam a vantagem da gravação dupla?
Ficamos livres pra alterar qualquer coisa a qualquer momento.

Mas o melhor é: tranquilidade
O que seria um problemão de converter todo aplicativo, foi transformado em probleminhas de solução rápida.
É já fazer e já liberar.

Se está terminado ou não, não importa, o que importa é que está sempre funcionando.
E seja DBF ou MySQL, os dois estão sempre atualizados e disponíveis pra uso.

Lembrando:
NÃO tenho nenhum problema com DBF compartilhado em rede.
Se não tenho problema com DBF, e nem problema com MySQL, a gravação dupla funciona perfeito.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

DBF para MySQL com gravação dupla

Mensagempor JoséQuintas » 13 Mai 2020 18:57

METHOD Email() CLASS JPCADASTROClass

   LOCAL cAssunto, cEmail, cTxt, mIdCadastro

   mIdCadastro := ::axKeyValue[ 1 ]
   IF mIdCadastro == 0
      MsgWarning( "Selecione primeiro o cliente" )
      RETURN NIL
   ENDIF
   WITH OBJECT ::cnSQL
      :cSQL := "SELECT * FROM JPCADASTRO WHERE IDCADASTRO = " + NumberSQL( mIdCadastro )
      :Execute()
      cEmail := :String( "CDEMAIL" )
      cAssunto = "Cad." + Str( mIdCadastro, 6 ) +  " " + :String( "CDNOME" )
      cTxt := []
      cTxt += [<html font size="2">]
      cTxt += [<table width="95%">]
      cTxt += [<tr><td></td></tr>]
      cTxt += [<tr><td align="CENTER">FICHA DE CADASTRO</td></tr>]
      cTxt += [<tr><td></td></tr>]
      cTxt += [<tr><td>CÓDIGO: ] + Str( mIdCadastro, 6 ) + [</td></tr>]
      cTxt += [<tr><td>NOME: ] + :String( "CDNOME" ) +  [</td></tr>]
      cTxt += [<tr><td>ENDEREÇO: ] + :String( "CDENDERECO" ) + [</td></tr>]
      cTxt += [<tr><td>BAIRRO: ] + :String( "CDBAIRRO" ) + [</td></tr>]
      cTxt += [<tr><td>CIDADE: ] + :String( "CDCIDADE" ) + [</td></tr>]
      cTxt += [<tr><td>UF: ] + :String( "CDUF" ) + [</td></tr>]
      cTxt += [<tr><td>CEP: ] + :String( "CDCEP" ) + [</td></tr>]
      cTxt += [<tr><td>CPF-CNPJ: ] + :String( "CDCNPJ" ) + [</td></tr>]
      cTxt += [<tr><td>INSCR.ESTADUAL: ] + :String( "CDINSEST" ) +   [</td></tr>]
      cTxt += [<tr><td>OUTRO DOCTO: ] + :String( "CDOUTDOC" ) +  [</td></tr>]
      cTxt += [<tr><td>EMAIL: ] + :String( "CDEMAIL" ) +  [</td></tr>]
      cTxt += [<tr><td></td></tr>]
      cTxt += [</table></font></html>]
      :CloseRecordset()
   ENDWITH
   IF Empty( cEmail )
      MsgWarning( "Cliente não contém endereço de email" )
      RETURN NIL
   ENDIF
   IF ! MsgYesNo( "Confirme o envio de email" )
      RETURN NIL
   ENDIF

   EnviaEmail( { cEmail },, cAssunto, cTxt )

   RETURN NIL


Pronto agora só MySQL.
Alterei a montagem pra antes da checagem e confirmação.
Porque isso?
Se um comando SQL já trás tudo, nem faço comandos intermediários, já pego o que interessa e encerro o uso do "temporário".
Só pra ter menos fonte.
O tempo de processamento aí nem importa, 1 segundo a mais ou a menos, não faz diferença.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

DBF para MySQL com gravação dupla

Mensagempor JoséQuintas » 14 Mai 2020 13:36

A que ponto chega a gravação dupla:

METHOD TelaDados( lEdit ) CLASS JPCADASTROClass

   LOCAL GetList := {}, cBloqueioDesc
   LOCAL cnSQL := ADOClass():New( AppConexao() )
   LOCAL mIdCadastro, mcdEndereco, mcdNumero, mcdCompl, mcdBairro, mcdCidade, mcdUf, mcdCep
   LOCAL mcdContato, mcdTelefone, mcdFax, mcdEndCob, mcdNumCob, mcdComCob, mcdBaiCob, mcdCidCob
   LOCAL mcdUFCob, mcdCepCob, mcdConCob, mcdTelCob, mcdFaxCob, mcdNomEnt, mcdEndEnt, mcdNumEnt
   LOCAL mcdComEnt, mcdBaiEnt, mcdCidEnt, mcdUFEnt, mcdCepEnt, mcdConEnt, mcdTelEnt, mcdFaxEnt
   LOCAL mcdNome, mcdApelido, mcdLimCre, mcdEmail, mcdEmaNfe, mcdEmaCon, mcdValMes, mcdCnpj
   LOCAL mcdInsEst, mcdOutDoc, mIdTriCad, mIdVendedor, midPortador, mIdForPag, mIdCliSta
   LOCAL mcdMapa, mIdMidia, mcdDivisao, mcdGrupo, mcdHomePage, mcdCnae, mIdTransp, mcdObs
   LOCAL mcdTelef2, mcdTelef3, mcdDatNas, mcdInfInc, mcdInfAlt, mcdCtaCon, mcdCtaJur, mcdCtaDes

   mIdCadastro := ::axKeyValue[ 1 ]
   WITH OBJECT cnSQL
      :cSQL := "SELECT * FROM JPCADASTRO"
      :Execute()
      Encontra( StrZero( mIdCadastro, 6 ), "jpcadastro", "numlan" )
      mcdEndereco := jpcadastro->cdEndereco
      mcdNumero   := jpcadastro->cdNumero
      mcdCompl    := jpcadastro->cdCompl
      mcdBairro   := jpcadastro->cdBairro
      mcdCidade   := jpcadastro->cdCidade
      mcdUf       := jpcadastro->cdUf
      mcdCep      := jpcadastro->cdCep
      mcdContato  := jpcadastro->cdContato
      mcdTelefone := jpcadastro->cdTelefone
      mcdFax      := jpcadastro->cdFax
      mcdEndCob   := jpcadastro->cdEndCob
      mcdNumCob   := jpcadastro->cdNumCob
      mcdComCob   := jpcadastro->cdComCob
      mcdBaiCob   := jpcadastro->cdBaiCob
      mcdCidCob   := jpcadastro->cdCidCob
      mcdUFCob    := jpcadastro->cdUFCob
      mcdCepCob   := jpcadastro->cdCepCob
      mcdConCob   := jpcadastro->cdConCob
      mcdTelCob   := jpcadastro->cdTelCob
      mcdFaxCob   := jpcadastro->cdFaxCob
      mcdNomEnt   := jpcadastro->cdNomEnt
      mcdEndEnt   := jpcadastro->cdEndEnt
      mcdNumEnt   := jpcadastro->cdNumEnt
      mcdComEnt   := jpcadastro->cdComEnt
      mcdBaiEnt   := jpcadastro->cdBaiEnt
      mcdCidEnt   := jpcadastro->cdCidEnt
      mcdUFEnt    := jpcadastro->cdUFEnt
      mcdCepEnt   := jpcadastro->cdCepEnt
      mcdConEnt   := jpcadastro->cdConEnt
      mcdTelEnt   := jpcadastro->cdTelEnt
      mcdFaxEnt   := jpcadastro->cdFaxEnt
      mcdNome     := jpcadastro->cdNome
      mcdApelido  := jpcadastro->cdApelido
      mcdLimCre   := jpcadastro->cdLimCre
      mcdEmail    := jpcadastro->cdEmail
      mcdEmaNfe   := jpcadastro->cdEmaNfe
      mcdEmaCon   := jpcadastro->cdEmaCon
      mcdValMes   := jpcadastro->cdValMes
      mcdCnpj     := jpcadastro->cdCnpj
      mcdInsEst   := jpcadastro->cdInsEst
      mcdOutDoc   := jpcadastro->cdOutDoc
      mIdTriCad   := Val( jpcadastro->cdTriCad )
      mIdVendedor := Val( jpcadastro->cdVendedor )
      midPortador := Val( jpcadastro->cdPortador )
      mIdForPag   := Val( jpcadastro->cdForPag )
      mIdCliSta   := Val( jpcadastro->cdStatus )
      mcdMapa     := jpcadastro->cdMapa
      mIdMidia    := Val( jpcadastro->cdMidia )
      mcdDivisao  := jpcadastro->cdDivisao
      mcdGrupo    := jpcadastro->cdGrupo
      mcdHomePage := jpcadastro->cdHomePage
      mcdCnae     := jpcadastro->cdCnae
      mIdTransp   := Val( jpcadastro->cdTransp )
      mcdObs      := jpcadastro->cdObs
      mcdTelef2   := jpcadastro->cdTelef2
      mcdTelef3   := jpcadastro->cdTelef3
      mcdDatNas   := jpcadastro->cdDatNas
      mcdInfInc   := jpcadastro->cdInfInc
      mcdInfAlt   := jpcadastro->cdInfAlt
      mcdCtaCon   := jpcadastro->cdCtaCon
      mcdCtaJur   := jpcadastro->cdCtaJur
      mcdCtaDes   := jpcadastro->cdCtaDes
      :CloseRecordset()
   ENDWITH


Já alterei pra pesquisar do MySQL, mas ainda mantendo a pesquisa no DBF.
Posso até alterar parcial de onde vém os campos.
Vai que entra ligação telefônica durante a alteração, posso liberar até pegando um campo de cada lugar.

Como dá pra perceber aí, existem campos que no DBF ainda são caractere.
Já fixei no aplicativo pra ser numérico, então na leitura/gravação do DBF converto de acordo com o tipo, mas já está resolvido pra MySQL.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

DBF para MySQL com gravação dupla

Mensagempor JoséQuintas » 14 Mai 2020 13:48

METHOD TelaDados( lEdit ) CLASS JPCADASTROClass

   LOCAL GetList := {}, cBloqueioDesc
   LOCAL cnSQL := ADOClass():New( AppConexao() )
   LOCAL mIdCadastro, mcdEndereco, mcdNumero, mcdCompl, mcdBairro, mcdCidade, mcdUf, mcdCep
   LOCAL mcdContato, mcdTelefone, mcdFax, mcdEndCob, mcdNumCob, mcdComCob, mcdBaiCob, mcdCidCob
   LOCAL mcdUFCob, mcdCepCob, mcdConCob, mcdTelCob, mcdFaxCob, mcdNomEnt, mcdEndEnt, mcdNumEnt
   LOCAL mcdComEnt, mcdBaiEnt, mcdCidEnt, mcdUFEnt, mcdCepEnt, mcdConEnt, mcdTelEnt, mcdFaxEnt
   LOCAL mcdNome, mcdApelido, mcdLimCre, mcdEmail, mcdEmaNfe, mcdEmaCon, mcdValMes, mcdCnpj
   LOCAL mcdInsEst, mcdOutDoc, mIdTriCad, mIdVendedor, midPortador, mIdForPag, mIdCliSta
   LOCAL mcdMapa, mIdMidia, mcdDivisao, mcdGrupo, mcdHomePage, mcdCnae, mIdTransp, mcdObs
   LOCAL mcdTelef2, mcdTelef3, mcdDatNas, mcdInfInc, mcdInfAlt, mcdCtaCon, mcdCtaJur, mcdCtaDes

   mIdCadastro := ::axKeyValue[ 1 ]
   WITH OBJECT cnSQL
      :cSQL := "SELECT * FROM JPCADASTRO"
      :Execute()
      Encontra( StrZero( mIdCadastro, 6 ), "jpcadastro", "numlan" )
      mcdEndereco := jpcadastro->cdEndereco
      mcdNumero   := jpcadastro->cdNumero
      mcdCompl    := jpcadastro->cdCompl
      mcdBairro   := jpcadastro->cdBairro
      mcdCidade   := jpcadastro->cdCidade
      mcdUf       := jpcadastro->cdUf
      mcdCep      := jpcadastro->cdCep
      mcdContato  := jpcadastro->cdContato
      mcdTelefone := jpcadastro->cdTelefone
      mcdFax      := jpcadastro->cdFax
      mcdEndCob   := jpcadastro->cdEndCob
      mcdNumCob   := jpcadastro->cdNumCob
      mcdComCob   := jpcadastro->cdComCob
      mcdBaiCob   := jpcadastro->cdBaiCob
      mcdCidCob   := jpcadastro->cdCidCob
      mcdUFCob    := jpcadastro->cdUFCob
      mcdCepCob   := jpcadastro->cdCepCob
      mcdConCob   := jpcadastro->cdConCob
      mcdTelCob   := jpcadastro->cdTelCob
      mcdFaxCob   := jpcadastro->cdFaxCob
      mcdNomEnt   := jpcadastro->cdNomEnt
      mcdEndEnt   := jpcadastro->cdEndEnt
      mcdNumEnt   := jpcadastro->cdNumEnt
      mcdComEnt   := jpcadastro->cdComEnt
      mcdBaiEnt   := jpcadastro->cdBaiEnt
      mcdCidEnt   := jpcadastro->cdCidEnt
      mcdUFEnt    := jpcadastro->cdUFEnt
      mcdCepEnt   := jpcadastro->cdCepEnt
      mcdConEnt   := jpcadastro->cdConEnt
      mcdTelEnt   := jpcadastro->cdTelEnt
      mcdFaxEnt   := jpcadastro->cdFaxEnt
      mcdNome     := jpcadastro->cdNome
      mcdApelido  := jpcadastro->cdApelido
      mcdLimCre   := :Number( "CDLIMCRE" )
      mcdEmail    := jpcadastro->cdEmail
      mcdEmaNfe   := jpcadastro->cdEmaNfe
      mcdEmaCon   := jpcadastro->cdEmaCon
      mcdValMes   := :Number( "CDVALMES" )
      mcdCnpj     := jpcadastro->cdCnpj
      mcdInsEst   := jpcadastro->cdInsEst
      mcdOutDoc   := jpcadastro->cdOutDoc
      mIdTriCad   := :Number( "CDTRICAD" )
      mIdVendedor := :Number( "CDVENDEDOR" )
      midPortador := :Number( "CDPORTADOR" )
      mIdForPag   := :Number( "CDFORPAG" )
      mIdCliSta   := :Number( "CDSTATUS" )
      mcdMapa     := jpcadastro->cdMapa
      mIdMidia    := :Number( "CDMIDIA" )
      mcdDivisao  := jpcadastro->cdDivisao
      mcdGrupo    := jpcadastro->cdGrupo
      mcdHomePage := jpcadastro->cdHomePage
      mcdCnae     := jpcadastro->cdCnae
      mIdTransp   := :Number( "CDTRANSP" )
      mcdObs      := jpcadastro->cdObs
      mcdTelef2   := jpcadastro->cdTelef2
      mcdTelef3   := jpcadastro->cdTelef3
      mcdDatNas   := jpcadastro->cdDatNas
      mcdInfInc   := jpcadastro->cdInfInc
      mcdInfAlt   := jpcadastro->cdInfAlt
      mcdCtaCon   := jpcadastro->cdCtaCon
      mcdCtaJur   := jpcadastro->cdCtaJur
      mcdCtaDes   := jpcadastro->cdCtaDes
      :CloseRecordset()
   ENDWITH


Por enquanto alterei os numéricos pra virem do MySQL, os demais vou ter que confirmar o tamanho da string.
Um detalhe interessante da minha classe aí é o seguinte: esses serão numéricos, NÃO IMPORTA se no MySQL são numéricos ou caractere.
Caso eu não tenha alterado ainda no MySQL, posso alterar depois, sem ter que mexer no fonte !!!
Ficou uma mão na roda isso.
Pra strings, eu até poderia alterar a classe pra pegar o tamanho direto da estrutura, mas achei que ficou mais flexível assim, porque facilita em browse, relatórios, etc.
E se fosse ambiente GUI, não precisaria disso, porque geralmente é definido no layout de tela/impressão.

Talvez até seja por isso que preferem uma IDE e/ou um gerador de relatórios.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

DBF para MySQL com gravação dupla

Mensagempor JoséQuintas » 14 Mai 2020 14:25

Pra estrutura, não tem muito o que fazer, ou o HeidiSQL, ou o fonte que cria a tabela em DBF ou MySQL.

stru.png


Dá pra ver mais embaixo que mantive o posicionamento do DBF.
É que não sei ainda se algum VALID pode usar o registro atual.
Fica assim por precaução, até terminar.

Ah é..... quanto de desempenho vou perder por fazer um SEEK no DBF? praticamente nulo.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

DBF para MySQL com gravação dupla

Mensagempor Itamar M. Lins Jr. » 15 Mai 2020 10:56

Ola!
Vc está declarando as variáveis fora do padrão.

lVar := .F./.T. //Logical
nVar := 0 //Numeric
dVar := Date() //Date
cVar := 'ABC' //Character
mVar := observação // Campo Memo
xVar := 0,1,2 ou 'ABC' //Numeric, Character


mData, mIdade, mEndereco... Não se usa mais, não é recomendado.

Saudações,
Itamar M. Lins Jr.
Avatar de usuário

Itamar M. Lins Jr.
Colaborador

Colaborador
 
Mensagens: 6927
Data de registro: 30 Mai 2007 11:31
Cidade/Estado: Ilheus Bahia
Curtiu: 309 vezes
Mens.Curtidas: 503 vezes

DBF para MySQL com gravação dupla

Mensagempor JoséQuintas » 15 Mai 2020 11:48

É que uso padronizado pra destacar o que vém de arquivo.
Se no arquivo é IdCadastro, em memória é mIdCadastro.

Mas pensando bem...
já estou começando a me perder sobre o que mudei ou não pra numérico.
o prefixo pode até ajudar agora.
Antes era sempre caractere, e agora não.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

DBF para MySQL com gravação dupla

Mensagempor claudiochaves » 06 Ago 2020 11:00

JoséQuintas escreveu:Alterando o fonte propriamente dito:

As rotinas anteriores, por enquanto são anotações apenas.

A primeira parte na conversão é atualizar DBF e MySQL ao mesmo tempo.
Então... aonde tem o REPLACE no DBF, acrescento o UPDATE para o MySQL.
E aonde tem o APPEND, acrescento o INSERT para o MySQL.

A partir daqui, gravação dupla, DBF e MySQL estão atualizados.
Mesmo esquema do DBF apenas atualiza o MySQL.

A partir daqui, poderia atualizar relatórios e outras pesquisas !!!


Ola, estou estudando sua técnica para agilizar minha migração, primeiro obrigado pela contribuição. No caso do update no mysql, você faz a clausula com todos os campos ou apenas os campos que tiveram alteração ? isto não ficou claro para mim.

Obrigado, abraços,
Claudio Chaves
Desenvolvedor
claudiochaves
Usuário Nível 1

Usuário Nível 1
 
Mensagens: 29
Data de registro: 28 Jul 2017 15:48
Cidade/Estado: campinas/sp
Curtiu: 19 vezes
Mens.Curtidas: 1 vez

DBF para MySQL com gravação dupla

Mensagempor JoséQuintas » 06 Ago 2020 12:23

claudiochaves escreveu:No caso do update no mysql, você faz a clausula com todos os campos ou apenas os campos que tiveram alteração ? isto não ficou claro para mim.


É uma gravação equivalente ao DBF.
Se no DBF gravava tudo, no MySQL também gravo tudo, e se era parcial, continua parcial.

O que era

REPLACE A1 WITH V1, A2 WITH V2, A3 WITH V3

foi substituído por um array bidimensional

{ { a1, v1 }, { a2, v2 }, { a3, v3 } }

Só pra dar idéia do uso disso no DBF:

SELECT TABELA
FOR EACH oCampo IN CamposList
REPLACE &( oCampo[ 1 ] ) WITH oCampo[ 2 ]
NEXT

Só pra dar idéia do uso no MySQL:

"INSERT INTO TABELA ( " + lista de campos do array + " ) VALUES ( " + lista de valores do array + ")"

O mesmo na alteração, sendo que:

No DBF: primeiro um SEEK pra posicionar antes do replace

No MySQL: indicar a chave UPDATE TABELA SET CAMPO1=VALOR1,... WHERE chave = x
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Próximo



Retornar para Contribuições, Dicas e Tutoriais

Quem está online

Usuários vendo este fórum: Nenhum usuário registrado online e 14 visitantes


Ola Amigo, espero que meu site e forum tem lhe beneficiado, com exemplos e dicas de programacao.
Entao divulgue o link da Doacao abaixo para seus amigos e redes sociais ou faça uma doacao para o site forum...
MUITO OBRIGADO PELA SUA DOACAO!
Faça uma doação para o forum
cron
v
Olá visitante, seja bem-vindo ao Fórum Clipper On Line!
Efetue o seu login ou faça o seu Registro