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

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

Meu modo de trabalho

Mensagem por JoséQuintas »

Tem mais um ponto importantíssimo nisso aí:

é um comando SQL, e um browse...
Qualquer linguagem de programação tem isso.

Sabem como era no Visual Basic 6, de 20 anos atrás?
Exatamente isso.
Um texto digitado, que é o comando SQL, e o GRID.

Entenderam? não está preso a DBF, e nem mesmo ao Harbour !!!

Estou confirmando isso na prática agora.
Abandonar o mecanismo DBF é o primeiro passo pra evolução e pra liberdade !!!!
Pode ser com ADO, a Microsoft deixou o ADO disponível pra todos, DE GRAÇA, há 20 anos.
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

Meu modo de trabalho

Mensagem por JoséQuintas »

Situação em 20/11/2019: 37 DBFs
Situação em 22/12/2019: 30 DBFs, e 48 no MySQL.
Usando cliente com mais opções em uso como referência 813MB em DBF, e 3.7GB em MySQL.
Não anotei outras referências.
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

Meu modo de trabalho

Mensagem por JoséQuintas »

Nos meus fontes eu já usava classe, em muita coisa, então pra muita coisa foi só ajustar as classes.

O cadastro de veículos:

Código: Selecionar todos

PROCEDURE PJPVEICULO

   LOCAL oFrm := JPVEICULOClass():New()

   IF ! AbreArquivos( "jpcadastro", "jpcidade", "jpconfi", "jpempresa", "jpitem", "jpitped", ;
      "jpnotfis", "jpnumero", "jppedido", "jppreco", "jpsenha", "jptabel", "jpuf" )
      RETURN
   ENDIF
   oFrm:Execute()

   RETURN
E a classe aplicada herança:

Código: Selecionar todos

CREATE CLASS JPVEICULOClass INHERIT FrmCadastroClass

   VAR    cDataTable INIT "JPVEICULO"
   VAR    cDataField INIT "IDVEICULO"
   VAR    axKeyField INIT { Space(6) }
   VAR    cnMySql    INIT ADOClass():New( AppConexao() )
   METHOD GridSelection()
   METHOD Especifico( lExiste )
   METHOD TelaDados( lEdit )
   METHOD Valida( cCodigo, lMostra, cCampo )

   ENDCLASS
No que o cadastro de veículso é diferente dos demais?
o browse, que pode ser usado em qualquer parte do aplicativo

Código: Selecionar todos

METHOD GridSelection() CLASS JPVEICULOClass

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

   WITH OBJECT cnMySql
      :cSql := "SELECT * FROM JPVEICULO ORDER BY VEPLACA"
      :Execute()
      oTBrowse := { ;
         { "CÓDIGO",    { || StrZero( :Number( "IDVEICULO" ), 6 ) } }, ;
         { "PLACA",     { || :String( "VEPLACA", 10 ) } }, ;
         { "MOTORISTA", { || :String( "VEMOTORI", 30 ) } }, ;
         { "TELEFONE",  { || :String( "VETELEFONE", 20 ) } }, ;
         { "CAP.TOT",   { || Transform( :Number( "VECAPACTOT" ), PicVal(6) ) } }, ;
         { "CAP.1",     { || Transform( :Number( "VECAPAC1" ), PicVal(6) ) } }, ;
         { "CAP.2",     { || Transform( :Number( "VECAPAC2" ), PicVal(6) ) } }, ;
         { "CAP.3",     { || Transform( :Number( "VECAPAC3" ), PicVal(6) ) } }, ;
         { "CAP.4",     { || Transform( :Number( "VECAPAC4" ), PicVal(6) ) } }, ;
         { "CAP.5",     { || Transform( :Number( "VECAPAC5" ), PicVal(6) ) } }, ;
         { "CAP.6",     { || Transform( :Number( "VECAPAC6" ), PicVal(6) ) } }, ;
         { "CAP.7",     { || Transform( :Number( "VECAPAC7" ), PicVal(6) ) } }, ;
         { "CAP.8",     { || Transform( :Number( "VECAPAC8" ), PicVal(6) ) } }, ;
         { "CAP.9",     { || Transform( :Number( "VECAPAC9" ), PicVal(6) ) } } }
      BrowseADO( cnMySql, oTBrowse, "VEPLACA,VEMOTORI,VETELEFONE", { || StrZero( :Number( "IDVEICULO" ), 6 ) } )
      :CloseRecordset()
   ENDWITH

   RETURN NIL
escolher um código específico:

Código: Selecionar todos

METHOD Especifico( lExiste ) CLASS JPVEICULOClass

   LOCAL GetList := {}, midVeiculo

   midVeiculo := ::axKeyValue[ 1 ]
   @ Row()+1, 20 GET midVeiculo PICTURE "@K 999999"  VALID NovoMaiorZero( @midVeiculo )
   Mensagem( "Digite código, F9 pesquisa, ESC sai" )
   READ
   Mensagem()
   IF LastKey() == K_ESC .OR. ( Val( midVeiculo ) == 0 .AND. ::cOpc != "I" )
      RETURN .F.
   ENDIF
   IF ! ::EspecificoExiste( lExiste, ADORecCount( "JPVEICULO", "IDVEICULO=" + StringSql( midVeiculo ) ) == 0 )
      RETURN .F.
   ENDIF
   ::axKeyValue := { midVeiculo }

   RETURN .T.
A tela de edição, que tem muito lixo por sinal, e não parei pra retirar a parte inútil...

Código: Selecionar todos

METHOD TelaDados( lEdit ) CLASS JPVEICULOClass

   LOCAL GetList := {}
   LOCAL midVeiculo, mvePlaca, mveMotori, mveTelefone, mveCapacTot, mveCapac1, mveCapac2, mveCapac3
   LOCAL mveCapac4, mveCapac5, mveCapac6, mveCapac7, mveCapac8, mveCapac9, mvePeso, mveInfInc, mveInfAlt

   midVeiculo := ::axKeyValue[1]
   WITH OBJECT ::cnMySql
      mvePlaca    := :String( "VEPLACA", 8 )
      mveMotori   := :String( "VEMOTORI", 30 )
      mveTelefone := :String( "VETELEFONE", 20 )
      mvePeso     := :Number( "VEPESO" )
      mveCapac1   := :Number( "VECAPAC1" )
      mveCapac2   := :Number( "VECAPAC2" )
      mveCapac3   := :Number( "VECAPAC3" )
      mveCapac4   := :Number( "VECAPAC4" )
      mveCapac5   := :Number( "VECAPAC5" )
      mveCapac6   := :Number( "VECAPAC6" )
      mveCapac7   := :Number( "VECAPAC7" )
      mveCapac8   := :Number( "VECAPAC8" )
      mveCapac9   := :Number( "VECAPAC9" )
      mveInfInc   := :String( "VEINFINC" )
      mveInfAlt   := :String( "VEINFALT" )
      :CloseRecordset()
   ENDWITH

   hb_Default( @lEdit, .F. )
   ::nNumTab := 1
   DO WHILE .T.
      ::ShowTabs()
      DO CASE
      CASE ::nNumTab == 1
         @ Row() + 1, 1 SAY "Núm. Lançto......:" GET midVeiculo WHEN .F.
         @ Row() + 2, 1 SAY "Placa............:" GET mvePlaca    PICTURE "!!!-9999" VALID ValidaPlaca( @mvePlaca )
//         @ Row() + 2, 1 SAY "CPF..............:" GET mveCPF      PICTURE "@9"       VALID OkGetCnpjCpf( @mvecpf, .T. )
         @ Row() + 2, 1 SAY "Motorista........:" GET mveMotori   PICTURE "@!"       VALID ! Empty( mveMotori )
         @ Row() + 1, 1 SAY "Telefone.........:" GET mveTelefone PICTURE "@!"
         @ Row() + 1, 1 SAY "Capacidade Total.:" GET mveCapacTot PICTURE "999,999"  VALID mveCapacTot > 0
         @ Row() + 1, 1 SAY "Peso do Veículo..:" GET mvePeso     PICTURE "999,999"
         @ Row() + 1, 1 SAY "Capac.Tanque 1...:" GET mveCapac1   PICTURE "999,999"
         @ Row() + 1, 1 SAY "Capac.Tanque 2...:" GET mveCapac2   PICTURE "999,999"
         @ Row() + 1, 1 SAY "Capac.Tanque 3...:" GET mveCapac3   PICTURE "999,999"
         @ Row() + 1, 1 SAY "Capac.Tanque 4...:" GET mveCapac4   PICTURE "999,999"
         @ Row() + 1, 1 SAY "Capac.Tanque 5...:" GET mveCapac5   PICTURE "999,999"
         @ Row() + 1, 1 SAY "Capac.Tanque 6...:" GET mveCapac6   PICTURE "999,999"
         @ Row() + 1, 1 SAY "Capac.Tanque 7...:" GET mveCapac7   PICTURE "999,999"
         @ Row() + 1, 1 SAY "Capac.Tanque 8...:" GET mveCapac8   PICTURE "999,999"
         @ Row() + 1, 1 SAY "Capac.Tanque 9...:" GET mveCapac9   PICTURE "999,999"
         @ Row() + 2, 1 SAY "Inf.Inclusão.....:" GET mveInfInc   WHEN .F.
         @ Row() + 1, 1 SAY "Inf.Alteração....:" GET mveInfAlt   WHEN .F.
      ENDCASE
      //SetPaintGetList( GetList )
      IF ! lEdit
         CLEAR GETS
         EXIT
      ENDIF
      Mensagem( "Digite campos, F9 Pesquisa, ESC Sai" )
      READ
      Mensagem()
      ::nNumTab += 1
      IF LastKey() == K_ESC
         EXIT
      ENDIF
      IF ::nNumTab > Len( ::acTabName )
         EXIT
      ENDIF
   ENDDO
   IF ! lEdit
      RETURN NIL
   ENDIF
   ::nNumTab := 1
   IF LastKey() == K_ESC
      RETURN NIL
   ENDIF
   WITH OBJECT ::cnMySql
      :QueryCreate()
      :QueryAdd( "VEPLACA", mvePlaca )
      :QueryAdd( "VEMOTORI", mveMotori )
      :QueryAdd( "VEPESO", mvePeso )
      :QueryAdd( "VECAPACTOT", mveCapacTot )
      :QueryAdd( "VECAPAC1", mveCapac1 )
      :QueryAdd( "VECAPAC2", mveCapac2 )
      :QueryAdd( "VECAPAC3", mveCapac3 )
      :QueryAdd( "VECAPAC4", mveCapac4 )
      :QueryAdd( "VECAPAC5", mveCapac5 )
      :QueryAdd( "VECAPAC6", mveCapac6 )
      :QueryAdd( "VECAPAC7", mveCapac7 )
      :QueryAdd( "VECAPAC8", mveCapac8 )
      :QueryAdd( "VECAPAC9", mveCapac9 )
      IF ::cOpc == "I"
         :QueryAdd( "VEINFINC", LogInfo() )
         IF Val( midVeiculo ) == 0
            midVeiculo := StrZero( :QueryExecuteInsert( "JPVEICULO" ), 6 )
         ELSE
            :QueryAdd( "IDVEICULO", midVeiculo )
            :QueryExecuteInsert( "JPVEICULO" )
         ENDIF
      ELSE
         :QueryAdd( "VEINFALT", LogInfo() )
         :QueryExecuteUpdate( "JPVEICULO", "IDVEICULO=" + StringSql( midVeiculo ) )
      ENDIF
   ENDWITH

   RETURN NIL
A validação de veículo e/ou placa que pode ser usada no aplicativo inteiro

Código: Selecionar todos

METHOD Valida( cCodigo, lMostra, cCampo ) CLASS JPVEICULOClass

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

   hb_Default( @lMostra, .T. )
   hb_Default( @cCampo, "codigo" )
   IF cCampo == "placa"
      IF Len( AllTrim( cCodigo ) ) < 2
         RETURN .T.
      ENDIF
      IF ! ValidaPlaca( cCodigo )
         RETURN .F.
      ENDIF
      IF ADORecCount( "JPVEICULO", "VEPLACA=" + StringSql( cCodigo ) ) == 0
         IF ! MsgYesNo( "Placa não utilizada antes. Continua?" )
            RETURN .F.
         ENDIF
         WITH OBJECT cnMySql
            :QueryCreate()
            :QueryAdd( "VEPLACA", cCodigo )
            :QueryExecuteInsert( "JPVEICULO" )
         ENDWITH
      ENDIF
   ELSE
      IF lMostra
         @ Row(), 32 SAY Space(10)
      ENDIF
      cCodigo := StrZero( Val( cCodigo ), 6 )
      IF ADORecCount( "JPVEICULO", "IDVEICULO=" + StringSql( cCodigo ) ) == 0
         MsgExclamation( "Veículo não cadastrado" )
         RETURN .F.
      ENDIF
      IF lMostra
         @ Row(), 32 SAY ADOField( "VEPLACA", "C", "JPVEICULO", "IDVEICULO=" + StringSql( cCodigo ) )
      ENDIF
   ENDIF

   RETURN .T.
Apenas ajustei o estilo DBF pra comportar o estilo ADO.
Mantendo o código caractere, apesar de salvar como numérico no MySQL, pra compatibilidade, até a completa migração pra MySQL.
aplicativo.png
Dizem que a GTWVG é complicada, enche de código fonte estranho dentro do fonte....
Tão vendo alguma coisa de GTWVG no fonte?
Pois é... uma IDE pra desenhar telas pra que? pra qual tela?
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

Meu modo de trabalho

Mensagem por JoséQuintas »

O meu aplicativo também tem uns fontes ridículos....
Algum dia devo ter criado, não sei se alguém usa, mas tá lá até hoje.
Vou alterar neste instante, porque estou querendo eliminar o JPESTOQUE.DBF
Este vai ser um bom exemplo de mudança pra SQL !!!

Código: Selecionar todos

/*
PESTOENTFOR - Consulta Entradas de Fornecedor
2000.12.05 José Quintas
*/

#include "inkey.ch"

PROCEDURE pEstoEntFor

   LOCAL m_TxtTmp, mFornec, GetList := {}, mTexto, mDocto

   IF ! AbreArquivos( "jpcadastro", "jpcidade", "jpconfi", "jpempresa", ;
      "jpestoque", "jpitem", "jpitped", "jpfiscal", "jpnotfis", "jpnumero", "jppedido", ;
      "jppreco", "jpsenha", "jptabel", "jpuf" )
      RETURN
   ENDIF
   m_TxtTmp  := MyTempFile( "DBF" )
   dbCreate( m_TxtTmp, { { "TEXTO", "C", 80, 0 } } )
   SELECT 0
   USE ( m_TxtTmp ) EXCLUSIVE ALIAS TEMP
   mFornec := Space(6)
   DO WHILE .T.
      @ 4, 0 SAY "Fornecedor.." GET mFornec PICTURE "@K 999999" VALID JPCADASTROClass():Valida( @mFornec )
      Mensagem( "Digite fornecedor, F9 pesquisa, ESC sai" )
      READ
      Mensagem()
      IF lastkey() == K_ESC
         EXIT
      ENDIF
      WSave()
      SELECT temp
      ZAP
      RecAppend()
      REPLACE temp->Texto WITH "FORNECEDOR (" + jpcadastro->idCadastro + ") " + jpcadastro->cdNome
      RecAppend()
      RecUnlock()
      SELECT jpestoque
      OrdSetFocus( "jpestoq5" )
      SEEK "2" + mFornec
      DO WHILE jpestoque->esTipLan == "2" .AND. jpestoque->esCliFor == mFornec .AND. ! Eof()
         GrafProc()
         mTexto := "Docto " + jpestoque->esNumDoc
         mTexto += " Emissao " + Dtoc( jpestoque->esDatLan )
         SELECT temp
         RecAppend()
         REPLACE temp->Texto WITH mTexto
         RecUnlock()
         mDocto := jpestoque->esNumDoc
         SELECT jpestoque
         DO WHILE mDocto == jpestoque->esNumDoc .AND. mFornec == jpestoque->esCliFor .AND. jpestoque->esTipLan == "2" .AND. ! Eof()
            GrafProc()
            Encontra( jpestoque->esItem, "jpitem","item" )
            mTexto := "   Qtde " + str( jpestoque->esQtde )
            mTexto += " Preco " + str( jpestoque->esValor )
            mTexto += " Item " + Left( jpitem->ieDescri, 70 )
            SELECT Temp
            RecAppend()
            REPLACE temp->Texto WITH mTexto
            RecUnlock()
            SELECT jpestoque
            SKIP
         ENDDO
      ENDDO
      SELECT temp
      RecAppend()
      REPLACE temp->Texto WITH "*** FIM ***"
      RecUnlock()
      Mensagem( "Selecione e tecle ENTER, ESC sai" )
      SELECT temp
      GOTO TOP
      FazBrowse()
      WRestore()
   ENDDO
   SELECT ( Select( "temp" ) )
   USE
   fErase( m_TxtTmp )

   RETURN
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

Meu modo de trabalho

Mensagem por JoséQuintas »

Pronto.
Pede pro servidor e mostra.
Não precisa de nenhum DBF agora, nem nada em disco.

Código: Selecionar todos

#include "inkey.ch"

PROCEDURE pEstoEntFor

   LOCAL mFornec := Space(6), GetList := {}, oTBrowse
   LOCAL cnMySql := ADOClass():New( AppConexao() )

   DO WHILE .T.
      @ 4, 0 SAY "Fornecedor.." GET mFornec PICTURE "@K 999999" VALID JPCADASTROClass():Valida( @mFornec )
      Mensagem( "Digite fornecedor, F9 pesquisa, ESC sai" )
      READ
      Mensagem()
      IF lastkey() == K_ESC
         EXIT
      ENDIF
      WITH OBJECT cnMySql
         :cSql := "SELECT LPAD( IDESTOQUE, 6, '0' ) AS ID, ESCLIFOR, ESDATLAN, ESNUMDOC, " + ;
            " ESQTDE, ESVALOR, ESQTDE * ESVALOR AS VALTOT, " + ;
            " LEFT( JPITEM.IEDESCRI, 50 ) AS ITENOME" + ;
            " FROM JPESTOQUE" + ;
            " LEFT JOIN JPITEM ON ESITEM=JPITEM.IDITEM" + ;
            " WHERE ESTIPLAN='2'" + ;
            " AND ESCLIFOR=" + StringSql( mFornec ) + ;
            " ORDER BY ESDATLAN DESC, ITENOME"
         :Execute()
         oTBrowse := { ;
            { "ID",      { || :String( "ID", 6 ) } }, ;
            { "DOCTO",   { || :String( "ESNUMDOC", 9 ) } }, ;
            { "DATA",    { || :Date( "ESDATLAN" ) } }, ;
            { "QTDE",    { || Transform( :Number( "ESQTDE" ), "@E 999,999,999.99" ) } }, ;
            { "VALOR",   { || Transform( :Number( "ESVALOR" ), "@E 999,999,999.9999" ) } }, ;
            { "TOTAL",   { || Transform( :Number( "VALTOT" ), "@E 999,999,999.99" ) } }, ;
            { "PRODUTO", { || :String( "ITENOME", 30 ) } } }
         BrowseADO( cnMySql, oTBrowse, "ESNUMDOC,ITENOME" )
         :CloseRecordset()
      ENDWITH
   ENDDO

   RETURN
Aproveitar fonte anterior?
De certa forma aproveitou a lógica, mas o fonte, quem se importa.

O que tem no fonte?
Pede pro servidor e faz um browse, nenhum processamento no terminal ou no aplicativo.

Trazer total pronto, ou multiplicar no browse? talvez... pode economizar alguns milésimos de segundo...
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

Meu modo de trabalho

Mensagem por JoséQuintas »

Agora pensando numa coisa:

Se não depende de arquivo aberto....
Nada impede de embutir/chamar essa rotina direto no cadastro do fornecedor, por exemplo.

É disso que o usuário gosta: recursos na mão (ou no click).
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

Meu modo de trabalho

Mensagem por JoséQuintas »

Quase acabando com o uso do dbf jpestoque.
O alias aparece 76 vezes em todos os fontes, incluindo rotinas de conversão/atualização.
Falta pouco....
jpestoque.png
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

Meu modo de trabalho

Mensagem por asimoes »

Quintas,

Nas minhas consultas, percebi que criar indices temporários é muito mais rápido que set filter to...

A vantagem disso é que que informo uma chave de ordenação e um filtro usando a clausula "for" que é equivalente ao "where" do sql

ainda de quebra posso usar OrdScope, OrdKeyCount...
►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

Meu modo de trabalho

Mensagem por JoséQuintas »

asimoes escreveu:Nas minhas consultas, percebi que criar indices temporários é muito mais rápido que set filter to...
A vantagem disso é que que informo uma chave de ordenação e um filtro usando a clausula "for" que é equivalente ao "where" do sql ainda de quebra posso usar OrdScope, OrdKeyCount...
Também tinha o sub-index, usava em SIXCDX.

INDEX ON .... FOR ... WHILE ...

Um índice criado a partir do índice atual, que pode servir pra algum tipo de filtro, pra ganhar tempo.

Mas estou encerrando com DBF.

Repetir o que já disse antes:
Trazer do MySQL é 1 segundo.
Gravar isso em DBF LOCAL, demora minutos.
Usar DBF deixou totalmente de fazer sentido.

Sinceramente...
Quer velocidade com DBF?
Use ADS LOCAL e comando SQL.
SEM ÍNDICE vai ser mais rápido do que qualquer outra alternativa.
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

Meu modo de trabalho

Mensagem por JoséQuintas »

Um exemplo de uso do sub-índice:

tem lá o movimento por data:

OrdSetFocus( "ordemdata" )
SEEK Dtos( "20191201" )
INDEX ON produto WHILE Data <= Ctod("31/12/2019")

Nesse caso vai usar o índice por data, usando só os lançamentos do mês, pra criar um índice por produto.

Mais fácil e rápido no MySQL... rs...
SELECT * FROM MOVIMENTO WHERE DATA BETWEEN ... ORDER BY PRODUTO
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

Meu modo de trabalho

Mensagem por asimoes »

Trabalhamos com Oracle desde 2001, sei do que você está falando.
Mas ainda existe sistema legado ( dbf ) ai optamos por manter do jeito que está, até converter para c#, enquanto isso, tem esse recurso do temporário.
►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

Meu modo de trabalho

Mensagem por JoséQuintas »

Última alteração de 2019:
Toda movimentação de estoque agora é exclusiva em MySQL.
Isso inclui relatórios, consultas, arquivo de envio pra ANP, etc.
Sem mais leitura ou gravação em DBF pra estoque.
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

Meu modo de trabalho

Mensagem por JoséQuintas »

Ainda estou eliminando JPNOTFIS.DBF, esse é o foco central, porque é o maior DBF de todos.
De um modo geral, em certos fontes é mais fácil eliminar vários DBFs de uma vez do que um só.
E também é interessante já ir testando um uso "mais avançado", pra ver se o comportamento é o esperado.
jpnotfis.png
Lembrando:
As gravações já estão duplicadas em DBF e MySQL.
Estou alterando agora as leituras, pra usar somente o MySQL.

Não tinha pensado nisso antes:

Mesmo que fosse alguma LIB do Harbour, até mesmo se fosse uma RDDSQL da vida, eu teria que fazer essa parte, de alterar ao máximo pra comandos SQL, pra ter velocidade.
Nem dá pra comparar o MEU tempo de migração com o de alguma RDDSQL, porque acabaria tendo que fazer isso do mesmo jeito.
Parece que na prática deu no mesmo, só alterei a ordem das coisas, fui direto pros finalmentes, antes de eliminar os DBFs.

Só uma coisa é certa:
Ver tudo funcionando mais rápido, deixa mais empolgado pra terminar tudo mais rápido.
E todos já devem ter percebido como estou empolgado.... rs
E ainda tenho DBFs, ainda nem me livrei de todos eles !!!
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

Meu modo de trabalho

Mensagem por JoséQuintas »

jpnotfis.png
O jpnotfis.dbf é o que estou eliminando, mas todos os NÃO marcados com X estão dentro do MySQL.
Acabei acrescentando os outros pra facilitar.

Pensando bem... acho que dava pra eliminar o jpestoque primeiro...
Se é que ainda precisa dele... rs
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

Meu modo de trabalho

Mensagem por JoséQuintas »

Vixe... não precisa mais dele....
Eliminei a necessidade de um DBF e nem percebi kkkk
Não usa em mais lugar nenhum.
jpestoque.png
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/
Responder