Clipper On Line • Ver Tópico - Meu modo de trabalho

Meu modo de trabalho

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

Moderador: Moderadores

 

Meu modo de trabalho

Mensagempor JoséQuintas » 07 Mai 2020 12:00

Só complementando:

Tá demorando pra terminar a conversão?
E daí?
Nenhum cliente pediu MySQL, está tudo ficando mais rápido e continua tudo funcionando.

Detalhe: antes o campo de número bancário era de 10 posições ou mais, por enquanto limitando a 6 posições, e depois (ou durante) trocar pra numérico no MySQL, e gravar StrZero(x,6) no DBF.
Melhor até alterar a pesquisa pelo número bancário pra já considerar numérico.
Esse é mais um motivo pra eu fazer devagar, porque estou ajustando campos.

E esse negócio de ter ID único numérico pra tudo que é arquivo/tabela é fantástico, simplifica muuuito, não importa se usa SQL ou DBF.

Em todo caso: no MySQL usando INT(11) significa que estou aumentando os limites pra BILHÕES de tudo que é tabela. Nunca mais me preocupar sobre estourar limites.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 13473
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 837 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 11 Mai 2020 14:59

Erro de hoje:

SYSTEM ERROR
Error BASE/1081 Argument error: +
Called from IMPRIME(395)
Called from PFINANRELPAGAR(101)
Called from DO(0)
Called from RUNMODULE(106)
Called from BOXMENU(753)
Called from BOXMENU(740)
Called from MENUPRINC(588)
Called from SISTEMA(87)
Called from (b)MAIN(58)


Tem a ver, ao mesmo tempo que não tem a ver com a migração SQL.

               oPDF:DrawText( oPDF:nRow, 0, "***PORTADOR " + midPortador + ", " + Pad( AUXFINPORClass():Descricao( midPortador ), 30 ) + " ...:" )


Já comentei aqui: uma das mudanças que tenho feito é alterar campo chave de caractere pra numérico.

mIdPortador agora é numérico.

É por isso que eu disse que tem e não tem a ver... porque não é erro de migração SQL, e sim de mudança de estrutura pra aproveitar melhor recursos SQL.

É um erro DA MINHA MIGRAÇÃO, e não do MySQL... aliás, é uma variável.
E só acontece quando escolhe um determinado portador, na montagem de um sub-título que mostra opções selecionadas.

Dá pra considerar normal, porque aconteceria o mesmo com DBF. (apesar que no dbf continua como caractere, até sua extinção).
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 13473
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 837 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 11 Mai 2020 15:13

A correção, apenas o uso de Str():

oPDF:DrawText( oPDF:nRow, 0, "***PORTADOR " + Str( midPortador. 6 ) + ", " + Pad( AUXFINPORClass():Descricao( midPortador ), 30 ) + " ...:" )


O que leva a outra coisa: pra que continuar pesquisando o portador, se isso pode ser feito no próprio comando SQL?
Pois é... como eu já disse por aqui, é ir migrando devagar, e durante a migração vamos aprendendo e tirando cada vez mais proveito do SQL.

Usar SQLMIX é uma boa opção pra migração rápida, mas.... se até usando ADO diretamente essas coisas podem passar desapercebidas, imagem usando estilo DBF....

Convém destacar:

Isso NÃO tem a ver com escolher ADO pra conectar.
Isso está diretamente relacionado a tirar mais proveito do servidor MySQL e comandos SQL.
Talvez eu não tenha feito isso antes porque estava migrando uma tabela de cada vez, mas a partir da gravação dupla passou a ser possível tirar mais proveito de tudo, já que todas as tabelas ficaram disponíveis no MySQL.

E assim vai prosseguindo a minha conversão: devagar, até refazendo coisa que tinha feito antes, mas sempre em frente.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 13473
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 837 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 11 Mai 2020 15:20

JoséQuintas escreveu:mIdPortador agora é numérico.


Faltou acrescentar:
Durante a fase de migração, alterei essa função que trás a descrição pra aceitar tanto chave caractere como numérica.
Desta forma ela continuou valendo pra fontes novos e velhos.

Nada complicado, algo do tipo:

FUNCTION Mostra( mIdPortador )

IF ValType( mIdPortador ) == "C"
   mIdPortador := Val( mIdPortador )
ENDIF


Desse jeito, tanto faz se ele é passado como caractere ou numérico, vale pro DBF que é caractere e pro MySQL que é numérico.
E quando terminar tudo, será remover esse IF (e outros que existirem).

Corrigindo: vale pra fonte novo e fonte velho, porque nos novos é sempre numérico, porque o foco principal é no tipo final.
No caso de DBF, leio como Val( arquivo->portador ) e gravo como StrZero( nIdPortador, 6 ), assim o aplicativo passa a trabalhar somente com numérico.
E quando remover o DBF, já remove a conversão junto.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 13473
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 837 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 25 Mai 2020 13:16

Vou começar a alterar esta parte agora.
É uma demonstração interessante de como "pensar em modo MySQL" é diferente de "pensar em modo DBF".

METHOD UserFunction( lProcessou ) CLASS FinanEdReceberClass

   LOCAL oXmlPdf, nIdFinanceiro := ::axKeyValue[ 1 ]

   Encontra( StrZero( nIdFinanceiro, 6 ), "jpfinan", "numlan" )
   Encontra( jpfinan->fiCadastro, "jpcadastro", "numlan" )
   DO CASE
   CASE ::cOpc == "F3"
      ::GeraFatura()
   CASE ::cOpc == "O"
      PJPREGUSO( "JPFINAN", Val( jpfinan->idFinan ) )
   CASE ::cOpc == "W"
      IF Val( jpfinan->fiPedido ) != 0 .AND. ADORecCount( "JPNOTFIS", "NFPEDIDO = " + NumberSQL( jpfinan->fiPedido ) ) != 0
         PosicionaEmpresa( Val( jpfinan->nfFilial ) )
         oXmlPdf := XmlPdfClass():New()
         oXmlPdf:GetFromMySql( "", Val( jpfinan->fiNumDoc ), "55" )
         oXmlPdf:GeraPDF()
         PosicionaEmpresa()
      ELSE
         oXmlPdf := XmlPdfClass():New()
         oXmlPdf:GetFromMySql( "", Val( jpfinan->fiNumDoc ), "55", jpcadastro->cdCnpj )
         oXmlPdf:GeraPDF()
      ENDIF
   CASE ::cOpc == "Q"
      ::PesquisaDocto()
   CASE ::cOpc == "T"
      ::GuiHide()
      ::TrocaCheque()
      ::GuiShow()
   CASE ::cOpc == "B"
      ::BaixaDocto()
   OTHERWISE
      lProcessou := .F.
   ENDCASE

   RETURN lProcessou


Como já comentei por aqui, comecei eliminando um arquivo por vez, mas depois mudei de idéia no meio do caminho com a gravação dupla.
usa o JPFINAN - financeiro em DBF
pesquisa JPCADASTRO, em DBF, pra encontrar o cliente
pesquisa JPNOTFIS, em MYSQL, pra verificar se existe nota fiscal emitida

Usava o financeiro em DBF, posicionado em DBF, o registro atual.
Com base no ID ainda posiciono o DBF.

Dá pra perceber aí também que padronizei nIdFinanceiro, nIdFilial, nIdPedido, como numéricos, porque são campos chave, mesmo no DBF sendo caractere, porque no MySQL já são numéricos.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 13473
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 837 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 25 Mai 2020 13:24

Fazer em duas etapas pra facilitar, apesar que é pequeno e nem precisava.
Substitui o acesso aos campos por variáveis, porque isso virá do MySQL.

METHOD UserFunction( lProcessou ) CLASS FinanEdReceberClass

   LOCAL oXmlPdf, nIdFinanceiro, nIdPedido, nIdFilial, nNumDoc, cCnpj

   nIdFinanceiro := ::axKeyValue[ 1 ]

   Encontra( StrZero( nIdFinanceiro, 6 ), "jpfinan", "numlan" )
   Encontra( jpfinan->fiCadastro, "jpcadastro", "numlan" )
   nIdPedido := Val( jpfinan->fiPedido )
   nIdFilial := Val( jpfinan->nfFilial )
   nNumDoc   := Val( jpfinan->fiNumDoc )
   cCnpj     := jpcadastro->cdCnpj

   DO CASE
   CASE ::cOpc == "F3"
      ::GeraFatura()
   CASE ::cOpc == "O"
      PJPREGUSO( "JPFINAN", nIdFinanceiro )
   CASE ::cOpc == "W"
      IF Val( jpfinan->fiPedido ) != 0 .AND. ADORecCount( "JPNOTFIS", "NFPEDIDO = " + NumberSQL( nIdPedido ) ) != 0
         PosicionaEmpresa( nIdFilial )
         oXmlPdf := XmlPdfClass():New()
         oXmlPdf:GetFromMySql( "", nNumDoc, "55" )
         oXmlPdf:GeraPDF()
         PosicionaEmpresa()
      ELSE
         oXmlPdf := XmlPdfClass():New()
         oXmlPdf:GetFromMySql( "", nNumDoc, "55", cCnpj )
         oXmlPdf:GeraPDF()
      ENDIF
   CASE ::cOpc == "Q"
      ::PesquisaDocto()
   CASE ::cOpc == "T"
      ::GuiHide()
      ::TrocaCheque()
      ::GuiShow()
   CASE ::cOpc == "B"
      ::BaixaDocto()
   OTHERWISE
      lProcessou := .F.
   ENDCASE

   RETURN lProcessou


Agora é substituir a origem das variáveis para o MySQL.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 13473
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 837 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 25 Mai 2020 13:31

Pronto.
Um único comando resolveu tudo, até a parte de fonte anterior de MySQL.

METHOD UserFunction( lProcessou ) CLASS FinanEdReceberClass

   LOCAL oXmlPdf, nIdFinanceiro, nIdPedido, nIdFilial, nNumDoc, cCnpj
   LOCAL cnSQL := ADOClass():New( AppConexao() )

   nIdFinanceiro := ::axKeyValue[ 1 ]
   WITH OBJECT cnSQL
      :cSQL := "SELECT FIPEDIDO, NFFILIAL, FINUMDOC, FICADASTRO," + ;
         " JPNOTFIS.IDNOTFIS, JPNOTFIS.NFFILIAL, " + ;
         " JPCADASTRO.CDCNPJ " + ;
         " FROM JPFINAN " + ;
         " LEFT JOIN JPPEDIDO ON JPPEDIDO.IDPEDIDO = JPFINAN.FIPEDIDO" + ;
         " LEFT JOIN JPNOTFIS ON JPNOTFIS.NFPEDIDO = JPPEDIDO.IDPEDIDO" + ;
         " WHERE IDFINAN = " + NumberSQL( nIdFinanceiro )
      :Execute()
      nIdPedido := :Number( "FIPEDIDO" )
      nIdFilial := :Number( "NFFILIAL" )
      nNumDoc   := :Number( "FINUMDOC" )
      cCnpj     := :String( "CDCNPJ" )
      :CloseRecordset()
   ENDWITH

   DO CASE
   CASE ::cOpc == "F3"
      ::GeraFatura()
   CASE ::cOpc == "O"
      PJPREGUSO( "JPFINAN", nIdFinanceiro )
   CASE ::cOpc == "W"
      IF nIdPedido != 0 .AND. nIdFilial != 0
         PosicionaEmpresa( nIdFilial )
         oXmlPdf := XmlPdfClass():New()
         oXmlPdf:GetFromMySql( "", nNumDoc, "55" )
         oXmlPdf:GeraPDF()
         PosicionaEmpresa()
      ELSE
         oXmlPdf := XmlPdfClass():New()
         oXmlPdf:GetFromMySql( "", nNumDoc, "55", cCnpj )
         oXmlPdf:GeraPDF()
      ENDIF
   CASE ::cOpc == "Q"
      ::PesquisaDocto()
   CASE ::cOpc == "T"
      ::GuiHide()
      ::TrocaCheque()
      ::GuiShow()
   CASE ::cOpc == "B"
      ::BaixaDocto()
   OTHERWISE
      lProcessou := .F.
   ENDCASE

   RETURN lProcessou


Nota: já conferi as outras sub-rotinas chamadas, e não dependem mais do posicionamento do DBF.

Este trecho é interessante pelo seguinte:
Mostra que pode ser mais interessante mover vários arquivos de uma vez, ao invés de um por um.
E é justamente aí que a gravação dupla foi vantagem: ao invés de alterar o fonte pra um arquivo MySQL por vez, já altero o fonte em definitivo.

Por enquanto fica assim, depois se aprender algo mais prático, ou redesenhar as bases de dados, faço de outro jeito.
Isso também mostra porque já padronizei os fontes pra usar campos numéricos, diferentes do DBF, porque já estão usando o formato final do MySQL.

E mais uma "não visível":

NÃO precisa de arquivo aberto, ou arquivo posicionado, bastam as variáveis contendo a informação.
Se o usuário largar o aplicativo aberto.... trata-se somente do aplicativo aberto, e uma única conexão pra troca de mensagens com MySQL, e nada mais.

Se fosse DBF: arquivos abertos, índices abertos, no terminal e no servidor, mais tempo do Windows pra manter tudo conectado, etc. etc. etc.

Como eu já disse por aqui: pensar "igual SQL", e esquecer como o DBF funciona. Não ter o DBF aberto e posicionado e trazer tudo pronto são as principais diferenças.
E não foi usado disco pra nada, apenas troca de mensagens entre aplicativo e servidor.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 13473
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 837 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 25 Mai 2020 14:31

Ah sim, devem se perguntar: porque tive que usar o arquivo de PEDIDOS?

Tenho financeiro com número de pedido ZERO, e tenho nota fiscal com número de pedido ZERO.
Se relacionar os dois diretamente, pelo número de pedido, os zerados vão estar relacionados.
A saída que usei foi essa: não existe pedido ZERO, então ao relacionar com pedido, deixa de existir nota fiscal relacionada.

Como eu comentei antes, sou principiante, é meu primeiro ano de uso de MySQL pra valer.
Tenho muito que aprender, mas com certeza já sei que usando DBF + MySQL vou ficar limitado.
Então... é terminar usando o que já aprendi, e depois ver o que vou poder melhorar.

Já quem acha que já sei muito....
Lembram que já comentei: é usar o básico, e ficar forte no básico, com o básico forte, a gente se vira pra fazer o resto.
Praticamente até agora só tenho usado o básico.
Seria o equivalente do DBF pra fazer SEEK e SET RELATION e nada mais.

Acho que a parte que mencionei no início seria igual em DBF.
Algo do tipo:

SELECT 0
USE NOTAS INDEX NPEDIDOS
SELECT 0
USE PEDIDOS INDEX FPEDIDOS
SET RELATION TO PEDIDOS->IDPEDIDO INTO NOTAS
SELECT 0
USE FINANCEIRO
SET RELATION TO FINANCEIRO->PEDIDO INTO PEDIDOS; TO FINANCEIRO->FICADASTRO INTO CADASTRO


É até interessante isso: apesar de filtros parecidos, o que no DBF é a parte mais lenta, no MySQL é a parte mais rápida.

Mas então... estou usando bastante o básico, e ficando craque no básico.
É como se eu estivesse num "treinamento intensivo" do básico.
Depois... quando tudo estiver em MySQL... aí vou poder aprender e usar mais coisas.

O importante é: estou aprendendo, estou convertendo, está em uso nos clientes, está funcionando perfeito, os DBFs estão deixando de ser usados.
Se vou terminar este mês, este ano, ano que vém, no outro ano,.... tanto faz... estou indo sempre em frente.
Acho que deste ano não passa.

Lembrando:
já eliminei o uso de estoque.dbf e notafiscal.dbf, agora é o financeiro.dbf.
Mas conforme altero rotinas, aproveito pra eliminar o uso de outros DBFs também, como na rotina acima, que eliminei o uso do cadastro.dbf.
E em relatórios, que pegam informação de tudo que é lugar ao mesmo tempo.
Por isso acho que deste ano não vai passar, mesmo fazendo tudo devagar.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 13473
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 837 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 26 Mai 2020 11:46

Só pra corrigir: o comando SQL anterior deu erro.

É que coloquei pra pegar JPCADASTRO.CDCNPJ, mas não indiquei essa tabela como parte do comando, por isso deu erro de não encontrar o campo.

O MySQL poderia pegar automaticamente?
Sim, mas como o cadastro tem muitos registros, faltou indicar o relacionamento, pra ele saber qual registro pegar.
Ainda bem que ele exige isso, senão iria pegar todos os cadastros.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 13473
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 837 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 29 Mai 2020 13:43

Eba !!!!
Menos um.

sql.png


Terminei de eliminar o uso de DBF do financeiro, o JPFINAN.DBF.

Nesse cliente, como dá pra ver na imagem, baixando de 500MB pra 400MB em DBF.
estoque, financeiro, e outros, agora somente em MySQL.

E o jpfinan.dbf?
Se venho fazendo gravação dupla DBF + MySQL, e está funcionando com as informações do MySQL... esse DBF virou lixo.
Vou apenas manter por mais um tempo, só por precaução, mas já pode ir pro lixo.
O DBF deixou de ser atualizado, não usa pra mais nada mesmo.

Os próximos são pedidos e produtos de pedido, que representam 350MB dos 400MB restantes em DBF.
Lembrando que eles já estão em gravação dupla há tempos, e já alterei muitos fontes pra não usarem mais os DBFs desses dois.

Recomendo a gravação dupla pra todos.
Mudar de DBF pra MySQL... aos poucos.... sem o cliente perceber... é fantástico...
Erros acontecem, mas são poucos a cada mudança, e fica fácil resolver.

No meu caso continua sendo ADO puro.
Se por um acaso trocar de linguagem de programação - NÃO é essa a intenção - tá tudo no jeito.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 13473
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 837 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 11 Jun 2020 10:01

Tava olhando aonde falta alterar o uso do produtos de pedidos: JPITPED.
Procurei por jpitped-> nos fontes.

falta1.png


falta2.png


falat3.png


Lembrando que no meio disso tem a gravação dupla, que se trata apenas de apagar.
A conversão ainda vai ser mantida, apenas pra transferir pra MySQL quem ainda não transferiu.
Tá quase lá....
Mas com certeza, as partes mais "complicadas" ficaram para o final.
Restam praticamente 8 (oito) fontes.

Nota: omiti pelo menos uma página, porque é o mesmo fonte JPPEDIDO.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 13473
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 837 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 14 Jun 2020 10:44

Acho que ficou aceitável, com minha classe.

FUNCTION ClonarPedido( nIdPedido )

   LOCAL nIdItPed, cField
   LOCAL cnSQL := ADOCLass():New( AppConexao() )

   IF nIdPedido == 0
      RETURN NIL
   ENDIF
   IF ! MsgYesNo( "Criar um novo pedido igual ao atual?" )
      RETURN NIL
   ENDIF
   WITH OBJECT cnSQL
      :cSQL := "SELECT JPPEDIDO.*, JPITPED.*" + ;
         " FROM JPPEDIDO" + ;
         " LEFT JOIN JPITPED ON JPITPED.IPPEDIDO = JPPEDIDO.IDPEDIDO" + ;
         " WHERE IDPEDIDO = " + NumberSQL( nIdPedido )
      :Execute()
      :QueryCreate()
      :QueryAdd( "PDCONF", "N" )
      :QueryAdd( "PDDATEMI", Date() )
      :QueryAdd( "PDINFINC", LogInfo() )
      FOR EACH cField IN { "PDFILIAL", "PDTRANSA", "PDCADASTRO", "PDVENDEDOR", "PDTRANSP", "PDFORPAG" }
         :QueryAdd( cField, StrZero( :Number( cField ), 6 ) )
      NEXT
      FOR EACH cField IN { "PDPEDCLI" }
         :QueryAdd( cField, StrZero( :Number( cField ), 9 ) )
      NEXT
      FOR EACH cField IN { "PDCONTATO", "PDDIFCAL", "PDEMAIL", "PDOBS", "PDLEIS" }
         :QueryAdd( cField, :String( cField ) )
      NEXT
      FOR EACH cField IN { "PDPERDES", "PDPERADI", "PDVALCUS", "PDVALPRO", "PDVALNOT", "PDVALFRE", ;
         "PDVALSEG", "PDVALOUT", "PDVALEXT", "PDVALDES", "PDVALADI", "PDVALADU", "PDVALIOF", "PDIIBAS", ;
         "PDIIVAL", "PDIPIBAS", "PDICMVAL", "PDFCPVAL", "PDSUBBAS", "PDSUBVAL", "PDDIFVALI", "PDDIFVALF", ;
         "PDISSBAS", "PDISSVAL", "PDIPIVAL", "PDICMBAS", "PDPISBAS", "PDPISVAL", "PDCOFBAS", "PDCOFVAL", ;
         "PDICSBAS", "PDICSVAL", "PDIMPVAL" }
         :QueryAdd( cField, :Number( cField ) )
      NEXT
      nIdPedido := :QueryExecuteInsert( "JPPEDIDO" )
      :QueryAdd( "IDPEDIDO", StrZero( nIdPedido, 6 ) )
      jppedido->( :DBFQueryExecuteInsert( "JPPEDIDO" ) )
      DO WHILE ! :Eof()
         :QueryCreate()
         :QueryAdd( "IPPEDIDO", StrZero( nIdPedido, 6 ) )
         :QueryAdd( "IPINFINC", LogInfo() )
         FOR EACH cField IN { "IPFILIAL", "IPPRODUTO", "IPTRIBUT" }
            :QueryAdd( cField, StrZero( :Number( cField ), 6 ) )
         NEXT
         FOR EACH cField IN { "IPPEDCOM", "IPCFOP", "IPLEIS", "IPORIMER", "IPIPIICM", "IPIPICST", ;
            "IPIPIENQ", "IPICMCST", "IPDIFCAL", "IPPISCST", "IPPISENQ", "IPCOFCST", "IPCOFENQ" }
            :QueryAdd( cField, :String( cField ) )
         NEXT
         FOR EACH cField IN { "IPPRECUS", "IPPREPED", "IPQTDE", "IPVALCUS", "IPGARANTIA", "IPPRENOT", ;
            "IPVALADI", "IPVALFRE", "IPVALSEG", "IPVALOUT", "IPVALEXT", "IPVALADU", "IPVALIOF", "IPVALDES", ;
            "IPVALPRO", "IPVALNOT", "IPIIBAS", "IPIIALI", "IPIPIBAS", "IPIPIALI", "IPIPIVAL", "IPICMBAS", ;
            "IPICMALI", "IPICMRED", "IPICMVAL", "IPFCPALI", "IPFCPVAL", "IPICSBAS", "IPICSALI", "IPICSVAL", ;
            "IPSUBIVA", "IPSUBBAS", "IPSUBRED", "IPSUBALI", "IPSUBVAL", "IPDIFBAS", "IPDIFALIF", "IPDIFALIU", ;
            "IPDIFALII", "IPDIFVALI", "IPDIFVALF", "IPPISBAS", "IPPISALI", "IPPISVAL", "IPCOFBAS", "IPCOFALI", ;
            "IPCOFVAL", "IPISSBAS", "IPISSALI", "IPISSVAL", "IPIMPALI", "IPIMPVAL" }
            :QueryAdd( cField, :Number( cField ) )
         NEXT
         nIdItPed := :QueryExecuteInsert( "JPITPED" )
         :QueryAdd( "IDITPED", StrZero( nIdItPed, 6 ) )
         jpitped->( :DbfQueryExecuteInsert( "JPITPED" ) )
         :MoveNext()
      ENDDO
      :CloseRecordset()
   ENDWITH
   SubPedidoClass():CalculaValores( nIdPedido )

   RETURN NIL


Acabei separando em blocos.
Detalhe deste:
      FOR EACH cField IN { "PDFILIAL", "PDTRANSA", "PDCADASTRO", "PDVENDEDOR", "PDTRANSP", "PDFORPAG" }
         :QueryAdd( cField, StrZero( :Number( cField ), 6 ) )
      NEXT


Esses campos, no DBF são tipo caractere, e no MySQL são tipo numérico.
Depois, quando eliminar o DBF, talvez troque por INSERT ... ( SELECT )
Mas não vai ser muita vantagem, porque vai precisar indicar os campos do mesmo jeito.

Ou talvez seja, se eu cadastrar como uma Stored Procedure, porque aí não precisa nenhum fonte no aplicativo !!!
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 13473
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 837 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 14 Jun 2020 12:40

Uia.
Estou trabalhando na tela de pedidos.
É um bom exemplo pra comparar DBF com SQL.

telaped.png


Tem informação até demais:

- JPPEDIDO: pedidos
- JPITPED: produtos do pedido
- JPITEM: descrição dos produtos
- JPVENDEDOR: nome do vendedor
- JPCADASTRO: dados do cliente
- JPFORPAG: descrição da forma de pagamento
- JPTRANSA: descrição da transação
- JPNOTFIS: dados de nota fiscal, se existir

Em DBF, 8 arquivos + 8 índices, selecionar área, índice, pesquisar, do while nos produtos de pedido pesquisando os nomes dos produtos, etc.
Em SQL, um único comando

Em SQL fica complicado?
Depende do ponto de vista.
Se comparar com um único SEEK, parece complicado.
Se comparar com no mínimo 8 SEEKs, aí parece muito mais simples

      :cSQL := "SELECT JPPEDIDO.*, JPITPED.*, JPCADASTRO.CDVENDEDOR, JPCADASTRO.CDNOME, JPCADASTRO.CDUF," + ;
      " JPCADASTRO.CDCNPJ, JPCADASTRO.CDENDENT, JPITEM.IEDESCRI, JPFORPAG.FPDESCRI, " + ;
      " JPNOTFIS.NFFILIAL, JPNOTFIS.NFNOTFIS, JPNOTFIS.NFDATEMI, JPTRANSA.TRDESCRI," + ;
      " JPVENDEDOR.VDDESCRI" + ;
      " FROM JPPEDIDO" + ;
      " LEFT JOIN JPITPED ON JPITPED.IPPEDIDO = JPPEDIDO.IDPEDIDO" + ;
      " LEFT JOIN JPCADASTRO ON JPCADASTRO.IDCADASTRO = JPPEDIDO.PDCADASTRO" + ;
      " LEFT JOIN JPITEM ON JPITEM.IDPRODUTO = JPITPED.IPPRODUTO" + ;
      " LEFT JOIN JPNOTFIS ON JPNOTFIS.NFPEDIDO = JPPEDIDO.IDPEDIDO" + ;
      " LEFT JOIN JPTRANSA ON JPTRANSA.IDTRANSA = JPPEDIDO.PDTRANSA" + ;
      " LEFT JOIN JPVENDEDOR ON JPVENDEDOR.IDVENDEDOR = JPPEDIDO.PDVENDEDOR" + ;
      " LEFT JOIN JPFORPAG ON JPFORPAG.IDFORPAG = JPPEDIDO.PDFORPAG" + ;
      " WHERE IDPEDIDO = " + NumberSQL( nIdPedido )


Aproveitar pra explicar, porque acaba sendo relativamente simples.

os campos que eu quero
      :cSQL := "SELECT JPPEDIDO.*, JPITPED.*, JPCADASTRO.CDVENDEDOR, JPCADASTRO.CDNOME, JPCADASTRO.CDUF," + ;
      " JPCADASTRO.CDCNPJ, JPCADASTRO.CDENDENT, JPITEM.IEDESCRI, JPFORPAG.FPDESCRI, " + ;
      " JPNOTFIS.NFFILIAL, JPNOTFIS.NFNOTFIS, JPNOTFIS.NFDATEMI, JPTRANSA.TRDESCRI," + ;
      " JPVENDEDOR.VDDESCRI" + ;


qual a tabela base e filtro, que neste caso só usa a tabela base

      " FROM JPPEDIDO" + ;
     ..
      " WHERE IDPEDIDO = " + NumberSQL( nIdPedido )


e os relacionamentos, como se fosse uma linha pra cada SEEK em cada tabela

      " LEFT JOIN JPITPED ON JPITPED.IPPEDIDO = JPPEDIDO.IDPEDIDO" + ;
      " LEFT JOIN JPCADASTRO ON JPCADASTRO.IDCADASTRO = JPPEDIDO.PDCADASTRO" + ;
      " LEFT JOIN JPITEM ON JPITEM.IDPRODUTO = JPITPED.IPPRODUTO" + ;
      " LEFT JOIN JPNOTFIS ON JPNOTFIS.NFPEDIDO = JPPEDIDO.IDPEDIDO" + ;
      " LEFT JOIN JPTRANSA ON JPTRANSA.IDTRANSA = JPPEDIDO.PDTRANSA" + ;
      " LEFT JOIN JPVENDEDOR ON JPVENDEDOR.IDVENDEDOR = JPPEDIDO.PDVENDEDOR" + ;
      " LEFT JOIN JPFORPAG ON JPFORPAG.IDFORPAG = JPPEDIDO.PDFORPAG" + ;


É só fazer os SAYs... e o TBrowse.
No caso dos produtos, já é feito o relacionamento de cada produto JPITPED com JPITEM.

Uma única consulta, e tá tudo na mão.
NADA de abrir arquivo, índice, etc. etc. etc.
NADA de pasta compartilhada, antivírus enchendo o saco, terminal fuçando arquivo, nada disso.
Vai uma mensagem pro servidor, volta uma mensagem com a informação.

Também é um bom exemplo pra mostrar o seguinte:
Eu poderia ter feito igual DBF, pesquisando uma coisa de cada vez?
Sim poderia.
Mas...

Se usar SQL igual DBF:

- pesquisar pedido
- pesquisar cliente
- pesquisar vendedor
- pesquisar transação
- pesquisar forma de pagamento
- pesquisar produtos de pedido
- fazer várias pesquisas de cada produto pra pegar descrição

Porque enviar/receber tanta mensagem, se uma única resolve?

Agora duas coisas interessantes:

- passar pra SQL ANTES de passar pra tela GUI/gráfica, pode facilitar muito.

- Isso acima é recurso de SQL, que NÃO encontramos em DBF.

E convém lembrar: SQL é recurso do servidor. Se está usando ADO ou SQLMIX ou outro, tanto faz.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 13473
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 837 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 14 Jun 2020 12:59

Tem mais uma coisa interessante:

Como uso nomes de campos diferentes em cada tabela, posso fazer esse JPPEDIDO.*, JPITPED.*
Se tivesse nome repetido, por exemplo CODCLI nos dois, aí já não daria pra fazer isso.

É por isso que a migração de DBF pra SQL pode ser diferente pra cada pessoa, porque cada um tem suas tabelas, e seu estilo de fazer as coisas.
De repente pode até valer a pena dar uma geral nos arquivos, e até nos fontes, preparando tudo antes de ir em frente.

De repente, o ideal pode ser mesmo do jeito que eu fiz.
Fui fazendo um arquivo por vez, e confirmando o que poderia facilitar em cada um.
E depois a gravação dupla, que já deu uma visão maior sobre tudo de uma vez.

Como eu disse: estou aprendendo conforme vou fazendo. Devagar meu uso/conhecimento de SQL foi/continua melhorando.

Até que comecei bem devagar, mas com o tempo, conforme fui me sentindo mais "confortável", com as coisas "se encaixando", fui acelerando um pouco mais.
Tô quase lá....

Certo? errado? sei lá.. escolhi esse caminho, gostei dele, e estou seguindo.
Por enquanto basta que funcione, da melhor maneira que eu puder fazer.
Depois... aí fica pra depois....
Aliás... desde o começo pensei assim... algumas coisas que fiz antes até já mudei depois kkkkk
Mas fazer o que? é assim mesmo, é ir fazendo e aprendendo, e fazendo e aprendendo....
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 13473
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 837 vezes

Meu modo de trabalho

Mensagempor asimoes » 14 Jun 2020 18:52

Quintas,

A sua tela iria ficar bunitinha na hwgui ou minigui
►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 de usuário

asimoes
Colaborador

Colaborador
 
Mensagens: 4578
Data de registro: 26 Abr 2007 16:48
Cidade/Estado: RIO DE JANEIRO-RJ
Curtiu: 310 vezes
Mens.Curtidas: 221 vezes

Anterior Próximo



Retornar para Contribuições, Dicas e Tutoriais

Quem está online

Usuários vendo este fórum: alaminojunior e 5 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