Copia de registros con FWH

Copia de registros con FWH

Postby thefull » Tue May 30, 2017 10:10 am

Buenas os dejo un tip por si es de ayuda.

Hoy he tenido que traspasar datos de una tabla a otra, pero con el problema añadido que es que quiero marcar el registro traspasado como procesado.
No he logrado hacerlo como quería con el APPEND FROM .... pues no tenemos el control sobre la tabla origen, y necesito marcarla.

Mirando en la clase DATABASE de FW, me encuentro con un par de funciones que vienen de perlas, pero no hay ejemplo , pues podemos uno;

Code: Select all  Expand view
 USE "ORIGEN" NEW
 ::oDbfOrigen := TDataBase():New()

  USE "DESTINO" NEW
  ::oDbfDestino := TDataBase():New()

  while !::oDbfOrigen:eof()
     dbselectarea( ::oDbfOrigen:cAlias )
     if !::oDbfOrigen:PROCESADA
        hRec := FW_RecToHash( )
       
        dbselectarea( ::oDbfDestino:cAlias )
        append blank
        FW_HashToRec( hRec )
     endif  
     
     dbselectarea( ::oDbfOrigen:cAlias )
     ::oDbfOrigen:PROCESADA := .T.
     ::oDbfOrigen:Save()

     ::oDbfOrigen:Skip()
  end while
 


La función FW_RecToHash( ), me devuelve un hash con los datos del registro actual de la tabla activa.
Así, una vez obtenido, cambia a la tabla destino hacemos un append blank, y soltamos el contenido ;
FW_HashToRec( hRec )

A continuación, marca ya en la tabla origen que lo he procesado.
De esta manera, tenemos un control total sobre el traspaso de datos que con APPEND FROM.
Saludos
Rafa Carmona ( rafa.thefullARROBAgmail.com___quitalineas__)
User avatar
thefull
 
Posts: 729
Joined: Fri Oct 07, 2005 7:42 am
Location: Barcelona

Re: Copia de registros con FWH

Postby hmpaquito » Tue May 30, 2017 2:40 pm

Pues me aprovecho de la situacion y pongo la mia, que tiene como caracteristicas:

- Permite que dbfs origen no tengan todos los mismos campos o no esten en el mismo orden.
- Hipervelocidad 8)
- Compatible Harbour/ xHarbour / Clipper


Code: Select all  Expand view
FUNCTION Main()

   LOCAL nI, aPar, nLast

   SELECT 0
   USE Test1
   nLast:= LastRec()

   SELECT 0
   USE Test2
 
   FOR nI:= 1 TO nLast
     
      Test1-> ( dbGoto( nI) )
     
      APPEND BLANK
   
      aPar:= CopRegHiperVelocidad("Test1", Alias(), aPar)

   NEXT

RETURN NIL


FUNCTION CopRegHiperVelocidad(cAliOri, cAliDes, aPar)
   Local nI
   Local nFCount
   Local nPosOri
   Local cCampo
   
   IF aPar == NIL

      aPar:= {}

      nFCount:= (cAliDes)-> (FCount())

      #Define FG_(cAlias, nPos) ((cAlias)-> (FieldGet(nPos)))

      FOR nI:= 1 TO nFCount
         cCampo:= (cAliDes)-> (FieldName(nI))
         
         nPosOri:= (cAliOri)-> ( FieldPos(cCampo))

         IF nPosOri != 0

            (cAliDes)-> ( FieldPut(nI, FG_(cAliOri, nPosOri)))

            Aadd(aPar, {nI, nPosOri})

         ENDIF

      NEXT
   ELSE
      // La segunda y posterior vez: hipervelocidad

      nFCount:= Len(aPar)

      FOR nI:= 1 TO nFCount

         (cAliDes)-> ( FieldPut(aPar[nI, 1], FG_(cAliOri, aPar[nI, 2])))

      NEXT

   ENDIF

RETURN aPar
 
hmpaquito
 
Posts: 1482
Joined: Thu Oct 30, 2008 2:37 pm

Re: Copia de registros con FWH

Postby thefull » Tue May 30, 2017 6:44 pm

Mañana lo pruebo.
Haciendo pruebas de rendimiento me encuentro que append from tarda menos de un segundo, siendo la otra opción más de 45 segundos en
las mismas circunstancias, por lo tanto, voy a tener que rediseñarlo.

A tu hipervelocidad, si en vez de pasarle el array, creas una static a un hash, seria un poquito más elegante ;-)

Saludos
Saludos
Rafa Carmona ( rafa.thefullARROBAgmail.com___quitalineas__)
User avatar
thefull
 
Posts: 729
Joined: Fri Oct 07, 2005 7:42 am
Location: Barcelona

Re: Copia de registros con FWH

Postby hmpaquito » Tue May 30, 2017 8:41 pm

Parece que mi hipervelocidad es una lisiada comparada con __dbTrans() :)

Code: Select all  Expand view
/* __dbTrans( nDstArea, aFieldsStru, bFor, bWhile, nNext, nRecord, lRest ) -> <lSuccess> */

HB_FUNC( __DBTRANS )



https://github.com/harbour/core/blob/d8c6c562f3e5815217abeec5e145432bcff3e6df/src/rdd/dbcmd.c

No debe ser difícil de adaptarla a cualquiera de las funciones de arriba. Además del código C, mas veloz, el copiar campo a campo mata la eficiencia.
hmpaquito
 
Posts: 1482
Joined: Thu Oct 30, 2008 2:37 pm

Re: Copia de registros con FWH

Postby AngelSalom » Wed May 31, 2017 10:32 am

Me encanta la hipervelocidad, hace bastantes años me estuve peleando con el tema de los traspasos entre tablas (básicamente para poder actualizar automáticamente las bases de datos de mis aplicaciones en los clientes). Tuve que pasar del APPEND FROM a pesar de su gran rapidez porque como hubiera un cambio en el tipo de datos, por ejemplo de carácter a numérico reventaba de lo lindo. De este modo tuve que crearme una función que controlara esto, además de ver si algún campo numérico había disminuido de tamaño, etc ... con lo que conseguí un proceso súper-robusto de actualización pero la hipervelocidad se fue al traste jejeje ... tampoco es que me preocupe mucho porque no es algo que se haga cada día, pero siempre está bien mejorar.

Estudio vuestras opciones a ver si acelero la cosa :mrgreen: :mrgreen:
Angel Salom
Visionwin Software - https://www.visionwin.com
------------------------------------------------------------
fwh 19.05 - harbour 3.2 - bcc 7.4
User avatar
AngelSalom
 
Posts: 708
Joined: Fri Oct 07, 2005 7:38 am
Location: Benicarló (Castellón ) - España

Re: Copia de registros con FWH

Postby thefull » Thu Jun 01, 2017 2:20 pm

Buenas

APPEND FROM , sería similar a los procesos Bulk de SQL Server, en un plis empujas todo ;-)

A veces , no queda más remedio que hacerlo de esta manera. En su día diseñe la aplicación de actualizaciones para la empresa, donde
se modifican/fusionan estructuras y se EMPUJA más de 3 gigas de datos.
El proceso tarda en algunas ocasiones más de una hora. Hacerlo uno a uno, es literalmente inviable.

En SQL, el intentar pasar datos haciendo INSERT, se demoraba más de 10 HORAS. Con un bulk, en un par de minutos.
A veces es necesario saber que volumen de datos estamos hablando para decantarse por una opción u otra.
De momento, tengo las 2 implementadas , por si acaso... :mrgreen:
Saludos
Rafa Carmona ( rafa.thefullARROBAgmail.com___quitalineas__)
User avatar
thefull
 
Posts: 729
Joined: Fri Oct 07, 2005 7:42 am
Location: Barcelona

Re: Copia de registros con FWH

Postby nageswaragunupudi » Sun Jun 11, 2017 12:53 am

Faster solution would be to use
aData := SRC->( FW_DbfToArray( [cFieldList], [bFor] ) )
DST->( FW_ArrayToDBF( aData, [cFieldList] ) )

cFieldList in FW_DbfToArray() can be a list of expressions too.
FW_ArrayToDBF() does a reasonable conversion of values too.

It is possible to copy to DBF with different fieldnames and fieldtypes

Example:
Code: Select all  Expand view

aData := SRC->( FW_DbfToArray( "TRIM(FIRST)+','+TRIM(LAST),CITY,SALARY+2000", { || .NOT. FIELD->TRANSFER } ) )
DST->( FW_ArrayToDBF( aData, "CUSTNAME,CITY,AMOUNT" ) )
 


Even a lot faster is to use SQL. Here is an example assuming both tables are not having fpt memo fields.
Code: Select all  Expand view
#include "fivewin.ch"
function Main()

   local cFolder
   local oCn, oRs, cSql

   cFolder  := "c:\fwh\samples\"  // your path to fwh samples folder. Trailing \ is important
   DBCREATE( cFolder + "
NEWTBL", { { "CUSTNAME", 'C', 60, 0 }, { "CITY", 'C', 30, 0 }, { "AMOUNT", 'N', 15, 2 } }, "DBFNTX" )

   oCn   := FW_OpenAdoConnection( cFolder )
   if oCn == nil
      ? "
failed to connect"
   else
      ? "
connection successful"
      cSql  := "
INSERT INTO NEWTBL (CUSTNAME,CITY,AMOUNT) " + ;
               "
SELECT TRIM(FIRST)+','+TRIM(LAST), CITY, SALARY+2000 FROM CUSTOMER WHERE AGE > 85"

      oCn:Execute( cSql )
      ocn:close()
   endif
   xbrowser cFolder + "
NEWTBL.DBF"

return nil

Please build and try this sample. You will get the best speed.
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
 
Posts: 10243
Joined: Sun Nov 19, 2006 5:22 am
Location: India

Re: Copia de registros con FWH

Postby Carlos Mora » Mon Jun 12, 2017 7:38 am

Tal y como dice Paquito, __dBTrans() es un misil. No hay comparación. Hice la siguiente prueba, intercalada entre código ya existente para aprovechar una tabla de las gordas y con muchos registros.

Code: Select all  Expand view
     
      dbCreate( 'Prueba', Creditos->( dbStruct() ) )
      USE Prueba NEW
      /* __dbTrans( nDstArea, aFieldsStru, bFor, bWhile, nNext, nRecord, lRest ) -> <lSuccess> */
      SELECT Creditos
      __dbTrans( Select( 'Prueba' ), /* { 'NCREDITO', 'CODORG', 'FECHACRED', 'FACTURA' }*/,,,, )
      CLOSE Prueba
 


En un Pentium Dual de 1.73 Ghz (un portatil de hace 10 años) con un disco SATA I de 500Gb traspasa 50K reg con 54 campos incluyendo memos en 2.58 segundos. Si limito la cantidad de campos a los 4 primeros, el tiempo baja a 1.31 segundos. Imbatible.

Como sucede con muchas funciones, hay poca documentación de __dBTrans() (¿O soy yo que no me entero?) pero rebuscando por ahí en algún mensaje de las listas de Harbour se explica que nDstArea debe ser el número de la WorkArea destino, aFieldsStru puede ser o bien un array con los nombres de los campos, pero tambien acepta arrays de estructura completa como los que devuelve dBStruct(). El resto de los parámetros son los mismos que en los comandos clásicos.
Saludos
Carlos Mora
http://harbouradvisor.blogspot.com/
StackOverflow http://stackoverflow.com/users/549761/carlos-mora
“If you think education is expensive, try ignorance"
Carlos Mora
 
Posts: 988
Joined: Thu Nov 24, 2005 3:01 pm
Location: Madrid, España

Re: Copia de registros con FWH

Postby thefull » Wed Jun 14, 2017 1:48 pm

Carlos
La velocidad es BRUTAL!!
Ahora bien, el problema que tengo es que cada vez que se ha procesado, debo de grabar en el origen que se ha procesado, y ahí radica el problema.
Si uso el bFor para cambiar el estado, lo hace, pero lo hace ANTES de pasar el registro al destino, entonces me encuentro el tener que
modificar un campo a posterior, he visto por ahí un __dbUpdate() a ver si ha posterior, procesar para cambiar el estado.
Saludos
Rafa Carmona ( rafa.thefullARROBAgmail.com___quitalineas__)
User avatar
thefull
 
Posts: 729
Joined: Fri Oct 07, 2005 7:42 am
Location: Barcelona

Re: Copia de registros con FWH

Postby xmanuel » Wed Jun 14, 2017 10:13 pm

Rafa no sé exactamente lo que haces... pero y en dos vueltas? uno para pasar y otro para marcar!!!
______________________________________________________________________________
Sevilla - Andalucía
xmanuel
 
Posts: 756
Joined: Sun Jun 15, 2008 7:47 pm
Location: Sevilla

Re: Copia de registros con FWH

Postby thefull » Thu Jun 15, 2017 8:02 pm

Buenas Manuel , efictiviWOnder :mrgreen:

He estado enseñando a los compañeros Clipperianos , y no se lo creían ;-)
Saludos
Rafa Carmona ( rafa.thefullARROBAgmail.com___quitalineas__)
User avatar
thefull
 
Posts: 729
Joined: Fri Oct 07, 2005 7:42 am
Location: Barcelona

Re: Copia de registros con FWH

Postby thefull » Thu Jun 15, 2017 8:05 pm

Hi , thanks!
But the use __dbtrans () is BIG BIG BIG ;-)

nageswaragunupudi wrote:Please build and try this sample. You will get the best speed.
Saludos
Rafa Carmona ( rafa.thefullARROBAgmail.com___quitalineas__)
User avatar
thefull
 
Posts: 729
Joined: Fri Oct 07, 2005 7:42 am
Location: Barcelona

Re: Copia de registros con FWH

Postby Carlos Mora » Thu Jun 29, 2017 10:24 pm

thefull wrote:Carlos
La velocidad es BRUTAL!!
Ahora bien, el problema que tengo es que cada vez que se ha procesado, debo de grabar en el origen que se ha procesado, y ahí radica el problema.
Si uso el bFor para cambiar el estado, lo hace, pero lo hace ANTES de pasar el registro al destino, entonces me encuentro el tener que
modificar un campo a posterior, he visto por ahí un __dbUpdate() a ver si ha posterior, procesar para cambiar el estado.


Pregunta: Ese campo donde grabas si se actualizó... ¿Que guarda? ¿Booleano? Tal vez se pueda usar la lista de todos los campos excepto ese de estado, con lo que no se actualizaría.
Saludos
Carlos Mora
http://harbouradvisor.blogspot.com/
StackOverflow http://stackoverflow.com/users/549761/carlos-mora
“If you think education is expensive, try ignorance"
Carlos Mora
 
Posts: 988
Joined: Thu Nov 24, 2005 3:01 pm
Location: Madrid, España


Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 11 guests