FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour modificar el sistema cuando ya está distribuido
Posts: 479
Joined: Fri Feb 16, 2007 10:29 AM
modificar el sistema cuando ya está distribuido
Posted: Fri Mar 26, 2010 11:30 AM

Compañeros,

¿Como haceis cuando teneis que realizar una modificación que afecta a las estructura de las DBF y el aplicativo ya está distribuido entre muchos clientes?
Cuando no afecta a las DBF, se envia el EXE y listo, pero ¿y si afecta a las DBF?

Sin más, un saludo.
Lorenzo

Posts: 1364
Joined: Wed Jun 21, 2006 12:39 AM
Re: modificar el sistema cuando ya está distribuido
Posted: Fri Mar 26, 2010 01:12 PM

Yo he tenido ese problema y lo solucioné desde código. Si lo que quiero es agregar un campo, asigno a una variable la estructura de la base de datos y verifico si el campo a agregar se encuentra, si no está renombro la base y creo la nueva estructura y después appendo los datos. No sé si es la mejor manera pero me a dado resultado. Espero te sirva.

Posts: 1088
Joined: Fri Oct 07, 2005 03:33 PM
Re: modificar el sistema cuando ya está distribuido
Posted: Fri Mar 26, 2010 01:24 PM

Hola,

aqui puede ingresar el concepto de parche, el cual puede estar formado por el reemplazo del exe y/o solo un script que te permita modificar la estructura del BDF y hacer cambios y actualizaciones de la informacio de los mismos.

Seria interesante para ello, tener algo como era el FiveScript para mandar parches solo como codigo fuente (ofuscado), y aplicar el parche desde el exe, asi lo parches serian mas peque~nos (pocos bytes). Ademas podrias tener control de los parches aplicados y las secuencias de los mismos.

Por otra parte si utilizas ADS (local o remoto) a traves de SQL es muy sencillo y seguro realizar modificaciones a la estructura de la DB y a los datos

solo son ideas

saludos

Marcelo

Posts: 8515
Joined: Tue Dec 20, 2005 07:36 PM
Re: modificar el sistema cuando ya está distribuido
Posted: Fri Mar 26, 2010 01:54 PM
// hago asi:

Code (fw): Select all Collapse
FUNCTION CREARNUEVOS( oMeter, oText, oDlg, lEnd )


    LOCAL lExiste

    IF .NOT. FILE( "TERMINAL.DBF" )

       oText:SetText( " Processando, Aguarde... Criando TERMINAL.DBF " )

       DbCreate( "TERMINAL.DBF", { { "SERIALHD",   "C", 15, 00 }, ;
                                   { "TERMINAL",   "N", 05, 00 }, ;
                                   { "TERM_DESCR", "C", 20, 00 }, ;
                                   { "CAIXA",      "N", 03, 00 }, ;
                                   { "TAMANCUPOM", "C", 01, 00 }, ;
                                   { "SUPRIMECAB", "C", 01, 00 }, ;
                                   { "PORTALEITO", "C", 01, 00 }, ;
                                   { "PORTADOECF", "C", 01, 00 }, ;
                                   { "VERSAOECF",  "C", 02, 00 }, ;
                                   { "PORTABALAN", "C", 01, 00 }, ;
                                   { "PORTAGAVET", "C", 01, 00 }, ;
                                   { "ABRIRGAVET", "C", 20, 00 }, ;
                                   { "PORTAIMPCH", "C", 01, 00 }, ;
                                   { "MODIMPCHEQ", "C", 01, 00 }, ;
                                   { "MODELOECF",  "C", 01, 00 }, ;
                                   { "MTELAPAGTO", "C", 01, 00 }, ;
                                   { "TEFDISCADO", "C", 01, 00 }, ;
                                   { "TOTTERMINA", "N", 03, 00 }, ;
                                   { "LEITBALANC", "C", 01, 00 }, ;
                                   { "MODELBALAN", "C", 01, 00 }, ;
                                   { "DESCMAXIMO", "N", 05, 02 }, ;
                                   { "IMPALIQUOT", "C", 01, 00 }, ;
                                   { "PERM4PRECO", "C", 01, 00 }, ;
                                   { "VLMAXTROCO", "N", 06, 02 }, ;
                                   { "IMPROUTMIC", "C", 01, 00 }, ;
                                   { "IMPQTDECOP", "N", 01, 00 }, ;
                                   { "IMPCUPITEM", "C", 01, 00 }, ;
                                   { "SUPCODPROD", "C", 01, 00 }, ;
                                   { "PULARLINHA", "N", 02, 00 }, ;
                                   { "VELOCBALAN", "C", 04, 00 }, ;
                                   { "NAOCOMPCUP", "C", 01, 00 }, ;
                                   { "TECLAREDUZ", "C", 01, 00 }, ;
                                   { "TIPODESOM",  "C", 01, 00 }, ;
                                   { "VALMAXSANG", "N", 12, 02 }, ;
                                   { "VALMAXPROD", "N", 05, 00 }, ;
                                   { "BANNERTELA", "C", 01, 00 } } )
 
       USE TERMINAL ALIAS TERMINAL EXCLUSIVE NEW

       INDEX ON Field->TERMINAL TAG XTERMINAL TO TERMINAL FOR !DELETED()

       INDEX ON Field->CAIXA    TAG XCAIXA    TO TERMINAL FOR !DELETED()

       DbCloseAll()

    ENDIF

    IF .NOT. FILE( "TERMINAL.CDX" )

       USE TERMINAL ALIAS TERMINAL EXCLUSIVE NEW

       INDEX ON Field->TERMINAL TAG XTERMINAL TO TERMINAL FOR !DELETED()

       INDEX ON Field->CAIXA    TAG XCAIXA    TO TERMINAL FOR !DELETED()

       DbCloseAll()

    ENDIF

    DBCLOSEALL()

    IF FILE( "TERMINAL.DBF" )

       lExiste := .F.

       USE TERMINAL ALIAS TERMINAL EXCLUSIVE NEW

       cAlias := ALIAS()

       FOR nConta := 1 TO (cAlias)->(fCount())

          IF (cAlias)->(FieldName(nConta)) = "TIPODESOM"

             lExiste := .T.

             EXIT

          ENDIF

       NEXT

       //-> Nao existe o campo, TIPODESOM vai criar
       IF .NOT. lExiste

          //->Avisa e Vai Pedir a Senha Master
          AVISO_DE_ATUALIZACAO_DO_BANCO() //-> ESTA EM FUNCOES.PRG

          DBCLOSEALL()

          USE TERMINAL ALIAS TERMINAL EXCLUSIVE NEW

          COPY TO TERMICOP.DBF

          DBCLOSEALL()

          oText:SetText( " Processando, Aguarde... Criando TERMINAL.DBF " )

          DbCreate( "TERMINAL.DBF", { { "SERIALHD",   "C", 15, 00 }, ;
                                      { "TERMINAL",   "N", 05, 00 }, ;
                                      { "TAMANCUPOM", "C", 01, 00 }, ;
                                      { "SUPRIMECAB", "C", 01, 00 }, ;
                                      { "PORTALEITO", "C", 01, 00 }, ;
                                      { "PORTADOECF", "C", 01, 00 }, ;
                                      { "VERSAOECF",  "C", 01, 00 }, ;
                                      { "PORTABALAN", "C", 01, 00 }, ;
                                      { "PORTAGAVET", "C", 01, 00 }, ;
                                      { "ABRIRGAVET", "C", 20, 00 }, ;
                                      { "PORTAIMPCH", "C", 01, 00 }, ;
                                      { "MODIMPCHEQ", "C", 01, 00 }, ;
                                      { "MODELOECF",  "C", 01, 00 }, ;
                                      { "MTELAPAGTO", "C", 01, 00 }, ;
                                      { "TEFDISCADO", "C", 01, 00 }, ;
                                      { "TOTTERMINA", "N", 03, 00 }, ;
                                      { "LEITBALANC", "C", 01, 00 }, ;
                                      { "MODELBALAN", "C", 01, 00 }, ;
                                      { "DESCMAXIMO", "N", 05, 02 }, ;
                                      { "IMPALIQUOT", "C", 01, 00 }, ;
                                      { "PERM4PRECO", "C", 01, 00 }, ;
                                      { "VLMAXTROCO", "N", 06, 02 }, ;
                                      { "IMPROUTMIC", "C", 01, 00 }, ;
                                      { "IMPQTDECOP", "N", 01, 00 }, ;
                                      { "IMPCUPITEM", "C", 01, 00 }, ;
                                      { "SUPCODPROD", "C", 01, 00 }, ;
                                      { "PULARLINHA", "N", 02, 00 }, ;
                                      { "VELOCBALAN", "C", 04, 00 }, ;
                                      { "NAOCOMPCUP", "C", 01, 00 }, ;
                                      { "TECLAREDUZ", "C", 01, 00 }, ;
                                      { "TIPODESOM",  "C", 01, 00 }, ;
                                      { "VALMAXSANG", "N", 12, 02 } } )

          DbCloseAll()

          USE TERMINAL ALIAS TERMINAL EXCLUSIVE NEW

          APPEND FROM TERMICOP.DBF

          INDEX ON Field->TERMINAL TAG TERMINAL TO TERMINAL FOR !DELETED()

          DbCloseAll()

       ENDIF

    ENDIF

RETURN NIL
João Santos - São Paulo - Brasil - Phone: +55(11)95150-7341
Posts: 111
Joined: Thu Jan 19, 2006 11:47 PM
Re: modificar el sistema cuando ya está distribuido
Posted: Fri Mar 26, 2010 03:14 PM
Aqui va otra:

Code (fw): Select all Collapse
USE(Pub:HFCLI) EXCLUSIVE NEW
IF !NETERR()
  StruVieja:=DBSTRUCT()
  StruNueva:=(Pub:HC)
  StrVieja:=LEN(StruVieja)
  StrNueva:=LEN(StruNueva)
  IF StrVieja#StrNueva   //Verifica  diferencia crea una nueva temporal 
    COPY TO COPIATER
    DBCREATE("TEMPOCLI",StruNueva)
    USE TEMPOCLI
    CMS=Pub:DIRARCEMP+Pub:CODEMP+"\HC"+Pub:CODEMP+Pub:ANO
    APPE FROM &CMS
    COPY TO (Pub:HFCLI)
   ELSE
    IF StrVieja==StrNueva   //Verifica si hay diferencia crea una nueva temporal 
      COPY TO COPIATINV
      DBCREATE("TEMPOCLI",StruNueva)
      USE TEMPOCLI
      CMS=Pub:DIRARCEMP+Pub:CODEMP+"\HC"+Pub:CODEMP+Pub:ANO
      APPE FROM &CMS
      COPY TO (Pub:HFCLI)
    ENDIF
  ENDIF
 ELSE
ENDIF


Saludos
Edgar Mauricio Arévalo Mogollón.
Bogotá DC. Colombia
FWH FTDN, xHarbour 1.2.1, Pelles C, Fivedit, Visual Studio Code, Borland 7.30, Mysql, Dbfs
http://www.hymplus.com http://www.hymlyma.com
Tratando de retomar la programación....
Posts: 592
Joined: Tue Mar 14, 2006 11:34 PM
Re: modificar el sistema cuando ya está distribuido
Posted: Fri Mar 26, 2010 04:59 PM

Loren,

El metodo que uso es muy parecido al que te han comentado los demas compañeros, salvo alguna variantes :

  • Tengo una DBF para almacenar la estructura de todas los archivos que usa la app.
  • Hice una programita que me lee la estructura y la guarda de todos los DBFs de la carpeta de Datos

Asi, cuando envio alguna actualizacion a los clientes hago lo siguiente :

  • Hago copia de la carpeta Datos a otro lado ( moverla )
  • Creo la carpeta Datos
  • Llamo una funcion que lee ese archivo que contiene las estructuras y genero todos los archivos ( vacios por supuesto )
  • Mando los datos del archivo "viejo" al "nuevo" con un Append From a todos los DBFs

y... Listo !!

De esta manera, no tengo ninguna estructura X por codigo.

Espero te sirva la idea.

Saludos

FWH 10.6 + xHarbour + Borland 582
Posts: 845
Joined: Sun Oct 09, 2005 05:36 PM
Re: modificar el sistema cuando ya está distribuido
Posted: Fri Mar 26, 2010 06:43 PM
Lorenzo,
aqui otra sugerencia como lo hago yo, todas son muy parecidas

al inicio de mi programa ejecuto una funcion: chk_bases()

luego en esta funcion, tengo todas las estructuras de las bases de datos, ejemplo:

Code (fw): Select all Collapse
Func Chk_Bases()

   cDbf := "Cultivos"
   T_aPaso := {}
   AADD(T_aPaso, {"CODIGO", "C", 3,0})  // codigo
   AADD(T_aPaso, {"NOMBRE", "C",30,0})  // nombre
   AADD(T_aPaso, {"RIEGOS", "N", 2,0})  // total de riegos incluido presiembra
   AADD(T_aPaso, {"LAMINA", "N", 6,2})  // lamina para determinar cuantos cm de agua necesita por hectarea
   IF !FILE(cDbf+".dbf")
      IF !MsgNoYes("Error Grave !! No Existe la Tabla ("+cDbf+")..."+CRLF+CRLF+;
         "Se Creará una Tabla VACIA."+CRLF+CRLF+;
         "¿ Desea Continuar ?",;
         "Confirme...")
         DbCloseAll()
         QUIT
      ENDIF
      DBCREATE(cDbf,T_aPaso,cDriver)
      DbCloseArea()
   ELSE
      VerificaBase(cDbf,T_aPaso)  --> aqui verifica si cambio la estructura o longitud de un campo, renombra la estructura, crea la nueva con el arreglo de arriba y hace un append de la base anterior a la nueva
   ENDIF


este proceso se valida cada vez que ingresa al sistema
Code (fw): Select all Collapse
PROCEDURE VerificaBase(cDbf,aFields)
 LOCAL oDfb, aStruct, x:=0, nPos:=0, lChange := .F.

   oDbf:=Abre_Dbf(cDbf)
   aStruct := (oDbf)->(DbStruct())

   IF Len(aStruct) <> Len(aFields)
      lChange := .T.
   ELSE
      FOR x := 1 TO Len(aFields)
          IF ( nPos := (oDbf)->(FieldPos(aFields[x,1])) ) == 0
*             msginfo("Agregar campo:  "+aFields[x,1]+"   "+aFields[x,2]+"   "+alltrim(str(aFields[x,3]))+","+alltrim(str(aFields[x,4]))+CRLF+CRLF+;
*                     " a la base de datos: "+cDbf,"Lista")
             lChange := .T.
             x:=LEN(aFields)+1
          ELSEIF (aStruct[nPos,2] <> aFields[x,2] .OR. aStruct[nPos,3] <> aFields[x,3] .OR. aStruct[nPos,4] <> aFields[x,4])
*             msginfo("Cambiar campo: "+aFields[x,1]+"    "+aFields[x,2]+"   "+alltrim(str(aFields[x,3]))+","+alltrim(str(aFields[x,4]))+CRLF+CRLF+;
*                     " a la base de datos: "+cDbf,"Lista")
             lChange := .T.
             x:=LEN(aFields)+1
          ENDIF
      NEXT
   ENDIF

   Cierra_dbf(cDbf)

   IF lChange
*      ? "va a entrar a renombrar la base actual"
      cFileOld := cPatD+cDbf+".dbf"
      cFileNew := cPatD+cDbf+".chg"
      cFileInd := cPatD+cDbf+".cdx"
      IF FILE(cFileNew)
         FERASE(cFileNew)
      ENDIF
      if FRENAME(cFileOld,cFileNew) == -1
         msgstop("File error: "+str(FERROR())+CRLF+CRLF+"Base de Datos: "+cDbf,"Atencion !!")
      else
*         ? "va a entrar a crear la nueva base"
         DBCREATE(cDbf,aFields,cDriver)
         USE (cDbf) SHARED NEW VIA cDriver
*         ? "va a agregar los registros de la base anterior"
         APPEND FROM (cFileNew)
         USE
*         ? "termino el proceso"
         FERASE(cFileInd)
*         FERASE(cFileNew)
      endif
   ENDIF
Return NIL


saludos
paco
____________________

Paco
Posts: 479
Joined: Fri Feb 16, 2007 10:29 AM
Re: modificar el sistema cuando ya está distribuido
Posted: Fri Mar 26, 2010 10:30 PM

mil gracias a todos....

con esta información tengo suficiente como para preparar mi nueva actualización.

Posts: 230
Joined: Sat Apr 19, 2008 10:28 PM
Re: modificar el sistema cuando ya está distribuido
Posted: Mon Mar 29, 2010 09:53 PM
Yo lo hago parecido. Tengo las estruturas en código, en una función chk_bases().
Cada vez que se entra al programa se comprueban las estructuras de todas las bases de datos y se modifica sólo si es necesario, avisando a otros usuarios que salgan, comprobando que los ficheros no están en uso, etc. Si falta algún indice se vuelve a crear .
2 errores que se pueden dar:
- Si un campo cambia, por ejemplo de numérico a caracter conservando el nombre del campo, al hacer el append da un error. Hay que añadir registro a registro en un bucle o dbeval.

- Si se usan indices CDX y es necesario reindexar es mejor borrar el antiguo fichero de indices y crearlo de nuevo, para eliminar los tags que ya no se usan.

También el número de versión lo tengo en código y en un fichero ini. De esta forma, si hay que hacer algunas tareas adicionales al actualizar la versión sólo se ejecutan una vez y se pueden quedar en el código, de forma que que todas las actualizaciones son acumulativas.

Code (fw): Select all Collapse
if !lee_ini("Actualizacion","Version_1.11",.f.)
 ....
tareas de la actualización de version
...
   escribe_ini("Actualizacion","Version_1.11",.t.)
endif

if !lee_ini("Actualizacion","Version_1.12",.f.)
...
   escribe_ini("Actualizacion","Version_1.12",.t.)
endif


Alvaro

Continue the discussion