I have on a project a Journal table where i write the modifications
Just send the journal to another system and recover it to replicate all the
changes made on the first computer.
I have on every table to sync a field named SYNCTAG C(12) with the
DefaultValue versynccode("TABLENAME") The default value is SYS(2015)
The table, on the description field has the following text:
TITLE=TABLENAME
SHARED=YES/NO
KEYFIELD=KEYFIELDS
And on the triggers field:
Insert trigger: jrn("tablename",1)
Update trigger: jrn("tablename",2)
Delete trigger: jrn("tablename",3)
Code to write the changes on the journal table and to recover it on a
different machine:
****************************************************************************
****************************************************************************
***************************************************************************
*** Writes modifications en the journal table
***************************************************************************
FUNCTION JRN
LPARAMETER lctabla, lnaccion
lcTabla = UPPER(ALLTRIM( lcTabla ))
*** Global flag to stop writing journal table while recovering data
IF VARTYPE(glstopjournal)="L"
IF glstopjournal=.T.
RETURN .T.
ENDIF
ENDIF
LOCAL vcttxsdata(1, 1)
LOCAL lcoldalias, lnOficina
IF EMPTY(lcTabla)
RETURN
ENDIF
IF !USED(lctabla)
RETURN
ENDIF
lcoldalias = ALIAS()
lcTabla = UPPER(ALLTRIM(lcTabla))
SELECT (lctabla)
*** Number of fields on the table
lnnumfields = AFIELDS(vctfields, lctabla)
DIMENSION vcttxsdata(lnnumfields, 2)
FOR i = 1 TO lnnumfields
vcttxsdata(i, 1) = vctfields(i,1) && field name
vcttxsdata(i, 2) = EVALUATE(vctfields(i,1)) && field value
ENDFOR
IF !USED("Journal")
USE journal ALIAS journal IN 0
ENDIF
lcmachinename = ALLTRIM(MachineName())
lcusername = ALLTRIM(UserName())
*** Writes on the journal
INSERT INTO journal (fechahora, machine, USER, tabla, accion,
pasado) VALUES (DATETIME(), lcmachinename, lcusername, lctabla, lnaccion,
.F.)
*** Writes on the memo field the vector
SELECT journal
SAVE TO MEMO txsdata ALL LIKE vcttxsdata
*** saves modifications
IF CURSORGETPROP("Buffering")=3
TABLEUPDATE(.T.,.T.)
ENDIF
*** HouseKeeping
RELEASE vcttxsdata
RELEASE vctfields
*** Restaura la tabla en que estaba, por si acaso
IF !EMPTY(lcoldalias)
SELECT (lcoldalias)
ENDIF
ENDFUNC
***************************************************************************
*** Recover data from the journal file
***************************************************************************
PROCEDURE RecoverJournal
LPARAMETER lcSyncDataFile
PUBLIC glStopJournal
glStopJournal = .T.
IF !USED(lcSyncDataFile)
USE &lcSyncDataFile IN 0 ALIAS SyncDataFile
ENDIF
SELECT SyncDataFile
SCAN
SELECT SyncDataFile
=
mergetx(UPPER(ALLTRIM(SyncDataFile.tabla)),SyncDataFile.accion,"SyncDataFile
")
SELECT SyncDataFile
ENDSCAN
RELEASE glStopJournal
ENDPROC
*
****************************************************************************
**********************************
*** Add, delete and modify data
****************************************************************************
**********************************
PROCEDURE MergeTx
LPARAMETER lcTabla, lnAccion, lcAliasJournal
EXTERNAL ARRAY vcttxsdata
LOCAL lnReturnValue
LOCAL vctCampos(1)
IF !USED(lcTabla)
lcAlias = JUSTSTEM(lcTabla)
USE (lcTabla) IN 0 ALIAS &lcAlias
ELSE
lcAlias = JUSTSTEM(lcTabla)
ENDIF
AFIELDS( vctCampos, lcalias )
DO CASE
CASE lnAccion=1 && INSERT *** New record
SELECT (lcAliasJournal)
RESTORE FROM MEMO txsdata ADDITIVE
IF VARTYPE(vcttxsdata)="U"
RETURN
ENDIF
lnVctLen = ALEN(vcttxsdata, 1)
SELECT (lcAlias)
IF lookforrecord(lcTabla,@vcttxsdata) <> 0 &&
Record not found
APPEND BLANK
FOR i = 1 TO lnVctLen
lcFieldName =
UPPER(ALLTRIM(vcttxsdata(i,1)))
IF ASCAN( vctCampos, lcFieldName ) >
0
REPLACE NEXT 1 &lcFieldName
WITH vcttxsdata(i,2)
ENDIF
ENDFOR
**** Guarda los cambios
SELECT (lcAlias)
IF CURSORGETPROP("Buffering")=3
TABLEUPDATE(.T.,.T.)
ENDIF
ENDIF
CASE lnAccion=2 && UPDATE *** Modify
SELECT (lcAliasJournal)
RESTORE FROM MEMO txsdata ADDITIVE
IF VARTYPE(vcttxsdata)="U"
RETURN
ENDIF
lnVctLen = ALEN(vcttxsdata, 1)
SELECT (lcAlias)
&& If the record exists modify it, if not creates it
lnReturnValue = lookforrecord(lcTabla,@vcttxsdata)
DO CASE
CASE lnReturnValue = 0 && Record found
SELECT (lcAlias)
IF NOT EOF()
FOR i = 1 TO lnVctLen
lcFieldName =
ALLTRIM(vcttxsdata(i,1))
lcFieldName = UPPER(
ALLTRIM(lcFieldName))
&& You can modify
the code here to skip primary key fields
IF ASCAN( vctCampos,
lcFieldName ) > 0
REPLACE NEXT
1 &lcFieldName WITH vcttxsdata(i,2)
ENDIF
ENDFOR
**** Save changes
SELECT (lcAlias)
IF
CURSORGETPROP("Buffering")=3
TABLEUPDATE(.T.,.T.)
ENDIF
ENDIF
CASE lnReturnValue = -1 && Record not found
SELECT (lcAlias)
APPEND BLANK
FOR i = 1 TO lnVctLen
lcFieldName =
ALLTRIM(vcttxsdata(i,1))
IF ASCAN( vctCampos,
lcFieldName ) > 0
REPLACE NEXT 1
&lcFieldName WITH vcttxsdata(i,2)
ENDIF
ENDFOR
**** Guarda los cambios
SELECT (lcAlias)
IF CURSORGETPROP("Buffering")=3
TABLEUPDATE(.T.,.T.)
ENDIF
ENDCASE
CASE lnAccion=3 && DELETE
SELECT (lcAliasJournal)
RESTORE FROM MEMO txsdata ADDITIVE
IF VARTYPE(vcttxsdata)="U"
RETURN
ENDIF
lnVctLen = ALEN(vcttxsdata, 1)
SELECT (lcAlias)
IF lookforrecord(lcTabla,@vcttxsdata)= 0
DELETE
ENDIF
**** Guarda los cambios
SELECT (lcAlias)
IF CURSORGETPROP("Buffering")=3
TABLEUPDATE(.T.,.T.)
ENDIF
ENDCASE
RETURN
ENDPROC
*
****************************************************************************
*********************
*** Looks for record...
****************************************************************************
*********************
FUNCTION LookForRecord
LPARAMETER lcTabla, vcttxsdata
LOCAL lcstring, lnPosition, lcClaves, lnCounter, lnNumItems, lnLoop,
lcNombreColumna, lcSyncTag
LOCAL lnReferencia
SET NEAR OFF && Evita que busque datos similares
SET EXACT ON && Fuerza la coincidencia exacta en strings
lcTabla = UPPER(ALLTRIM(lcTabla))
lnNumItems = ALEN(vcttxsdata, 1)
lcSyncTag = ""
lnOficina = 0
lnReferencia = 0
lcCompradCod = ""
lndemanda = 0
FOR lnLoop = 1 TO lnNumItems
lcNombreColumna = UPPER(ALLTRIM(vcttxsdata(lnLoop,1)))
DO CASE
CASE "SYNCTAG" $ UPPER(lcNombreColumna)
lcSyncTag =
vcttxsdata(lnLoop,2)
CASE "OFICINA" $ UPPER(lcNombreColumna)
lnOficina =
vcttxsdata(lnLoop,2)
CASE "REFERENCIA" $ UPPER(lcNombreColumna)
lnReferencia = vcttxsdata(lnLoop,2)
CASE "CODIGO" $ UPPER(lcNombreColumna)
IF lcTabla = "COMPRAD"
lcCompradCod = vcttxsdata(lnLoop,2)
ENDIF
CASE "DEMANDA" $ UPPER(lcNombreColumna)
IF lcTabla = "DEMANDA"
lnDemanda = vcttxsdata(lnLoop,2)
ENDIF
ENDCASE
ENDFOR
*** Empty Synctag = ERROR
IF EMPTY(lcSyncTag)
RETURN -3
ENDIF
*** Looks for the key
SELECT (lcTabla)
SET ORDER TO TAG SyncTag
IF SEEK( lcSyncTag )
RETURN 0
ELSE
RETURN -1
ENDIF
ENDFUNC
*
FUNCTION dato2string
LPARAMETER loDato
LOCAL lcReturnString
lcReturnString = ""
DO CASE
CASE VARTYPE(loDato)="C"
lcReturnString = CHR(34)+loDato+CHR(34)
CASE VARTYPE(loDato)="N"
lcReturnString = ALLTRIM(STR(loDato))
CASE VARTYPE(loDato)="Y"
lcReturnString = ALLTRIM(STR(loDato))
CASE VARTYPE(loDato)="L"
lcReturnString = IIF(loDato, ".T.", ".F.")
CASE VARTYPE(loDato)="O"
CASE VARTYPE(loDato)="G"
CASE VARTYPE(loDato)="D"
lcReturnString = "CTOD("+DTOC(loDato)+")"
CASE VARTYPE(loDato)="T"
lcReturnString = "CTOT("+TTOC(loDato)+")"
CASE VARTYPE(loDato)="X"
CASE VARTYPE(loDato)="U"
ENDCASE
RETURN lcReturnString
ENDFUNC
*
_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/profox
OT-free version of this list: http://leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message:
http://leafe.com/archives/byMID/profox/0B08A57A16F3435BBD2B7B27F11C0DF2@LENOVO1
** All postings, unless explicitly stated otherwise, are the opinions of the
author, and do not constitute legal or medical advice. This statement is added
to the messages for those lawyers who are too stupid to see the obvious.