Problema muy serio cn RC2 y MySql
Publicado: Lun Nov 23, 2009 3:30 pm
Buenas tardes:
Espero poder exponer el problema con claridad
Estamos pasando aplicaciones de DBF a MySql
Para eso hemos desarrollado un importador de un fichero DBF (oDbfOri) a
una tabla de MySQL (oSqlDes)
Este es el precedimiento que lee de oDbfOri y segun el tipo de campo
graba en oSqlDes
En este codigo solo se leen los 3000 primeros
Lo primero que descubrimos es que de un fichero de 58000 registros
,grabó 49000. Después de repetirlo varias veces, descubrimos que
efectivamente el sistema se 'comia' los registros.
Acotando el numero de registros, descubrimos que el error lo generaba de
manera aleatoria y con 3000 podemos documentarlo.
Utilizamos DataSets .
1º Creamos un registro vacio con :FastAddNEw() (con addnew() también
genera el mismo error)
2º En un for / next leemos los campos de oDbfOri y grabamos en
oSqlDwes , según corresponda el tipo de campo usando FieldPut
3º Cuando se ha realizado la grabación , añadimos un elemento al array
de control aDatosArray ( despues del :FastUpdate() )
4º Al finalizar del proceso visualizamos el array con una función
propia .(msgarray).
5º Logicamente es de esperar que por cada registro añadido ,genere un
Id nuevo y un registro en el fichero destino .
6º La sorpresa es lo que nos encontramos al revisar el array ,
despues de visualizar los registros en el origen y destino , por fin
descubrimos donde está el error .
Cuando genera los registros 2129 y 2130 ,genera el mismo ID para
varios registros ,claro en el fichero solo se guarda 1 puesto que es
primary key y unique. (Ver fichero adjunto)
Necesitamos la máxima respuesta en este asunto porque tenemos que
entregar 2 aplicaciones casi terminadas y no podemos hacerlo ante la
inseguridad del funcionamiento actual
//--- Codigo del importador -------------
El codigo está verificado y de hecho funciona bien los primeros 2000 y
pico registros.
with object ::oSqlDes
:Open()
nProBar := 0
do while ! ::oDbfOri:Eof() .and. ::oDbfOri:RecNo() < 3000
nProBar ++
:FastAddNew()
//---- Lectura de los datos y actualizacion -------------------
for nK := 1 to len(aCampos)
cFieldOri := allstring(aCampos[nK,1])
cFieldDes := allstring(aCampos[nK,2])
if :FieldPos(cFieldDes) == 0
msginfo("Error en campo destino "+cFieldDes)
endif
if valtype(::oDbfOri:FieldGetByName(cFieldOri)) == "C"
nAncho := :aFields[:FieldPos(cFieldDes)]:nLen
cCampo := ::oDbfOri:FieldGetByName(cFieldOri)
if :FieldSqlType(:FieldPos(cFieldDes)) == "BLOB" .or.
:FieldSqlType(:FieldPos(cFieldDes)) == "VARCHAR"
:FieldPut(:FieldPos(cFieldDes),cCampo)
elseif :FieldSqlType(:FieldPos(cFieldDes)) != "CHAR"
:FieldPut(:FieldPos(cFieldDes),val(cCampo))
else
:FieldPut(:FieldPos(cFieldDes),PADR(cCampo,nAncho))
endif
else
:FieldPut(:FieldPos(cFieldDes),::oDbfOri:FieldGetByName(cFie ldOri))
endif
next nK
:confechac := dtos(::oDbfOri:con_fec)
//---- Actualizacion concepto actividad
nActo := ::oDbfOri:FIeldGetByName("con_act")
if nActo > 0 .and. nActo <= len(::aActo)
:conactividad := val(::aActo[nActo])
endif
//---------------------------------------------------------- -------------
:FastUpdate()
aadd(aDatosArray,{:id,:connumero,:conHistoria,:confecha,:con ho1,:conho2})
::oDbfOri:Skip()
enddo
::oSqlDes:Update()
//----------- Actualizacion de cip y numero de historia
WaitOn("Actualizando contactos","Un momento...")
AppData:oSqlSource:Execute("UPDATE IGNORE contactos SET conhistoria
= (SELECT historiapac FROM pacientes WHERE codigopac = connumero ) WHERE
id > 0 ")
WaitOff()
End with
Un saludo y Gracias .
Juan José García .
BISOFT
Espero poder exponer el problema con claridad
Estamos pasando aplicaciones de DBF a MySql
Para eso hemos desarrollado un importador de un fichero DBF (oDbfOri) a
una tabla de MySQL (oSqlDes)
Este es el precedimiento que lee de oDbfOri y segun el tipo de campo
graba en oSqlDes
En este codigo solo se leen los 3000 primeros
Lo primero que descubrimos es que de un fichero de 58000 registros
,grabó 49000. Después de repetirlo varias veces, descubrimos que
efectivamente el sistema se 'comia' los registros.
Acotando el numero de registros, descubrimos que el error lo generaba de
manera aleatoria y con 3000 podemos documentarlo.
Utilizamos DataSets .
1º Creamos un registro vacio con :FastAddNEw() (con addnew() también
genera el mismo error)
2º En un for / next leemos los campos de oDbfOri y grabamos en
oSqlDwes , según corresponda el tipo de campo usando FieldPut
3º Cuando se ha realizado la grabación , añadimos un elemento al array
de control aDatosArray ( despues del :FastUpdate() )
4º Al finalizar del proceso visualizamos el array con una función
propia .(msgarray).
5º Logicamente es de esperar que por cada registro añadido ,genere un
Id nuevo y un registro en el fichero destino .
6º La sorpresa es lo que nos encontramos al revisar el array ,
despues de visualizar los registros en el origen y destino , por fin
descubrimos donde está el error .
Cuando genera los registros 2129 y 2130 ,genera el mismo ID para
varios registros ,claro en el fichero solo se guarda 1 puesto que es
primary key y unique. (Ver fichero adjunto)
Necesitamos la máxima respuesta en este asunto porque tenemos que
entregar 2 aplicaciones casi terminadas y no podemos hacerlo ante la
inseguridad del funcionamiento actual
//--- Codigo del importador -------------
El codigo está verificado y de hecho funciona bien los primeros 2000 y
pico registros.
with object ::oSqlDes
:Open()
nProBar := 0
do while ! ::oDbfOri:Eof() .and. ::oDbfOri:RecNo() < 3000
nProBar ++
:FastAddNew()
//---- Lectura de los datos y actualizacion -------------------
for nK := 1 to len(aCampos)
cFieldOri := allstring(aCampos[nK,1])
cFieldDes := allstring(aCampos[nK,2])
if :FieldPos(cFieldDes) == 0
msginfo("Error en campo destino "+cFieldDes)
endif
if valtype(::oDbfOri:FieldGetByName(cFieldOri)) == "C"
nAncho := :aFields[:FieldPos(cFieldDes)]:nLen
cCampo := ::oDbfOri:FieldGetByName(cFieldOri)
if :FieldSqlType(:FieldPos(cFieldDes)) == "BLOB" .or.
:FieldSqlType(:FieldPos(cFieldDes)) == "VARCHAR"
:FieldPut(:FieldPos(cFieldDes),cCampo)
elseif :FieldSqlType(:FieldPos(cFieldDes)) != "CHAR"
:FieldPut(:FieldPos(cFieldDes),val(cCampo))
else
:FieldPut(:FieldPos(cFieldDes),PADR(cCampo,nAncho))
endif
else
:FieldPut(:FieldPos(cFieldDes),::oDbfOri:FieldGetByName(cFie ldOri))
endif
next nK
:confechac := dtos(::oDbfOri:con_fec)
//---- Actualizacion concepto actividad
nActo := ::oDbfOri:FIeldGetByName("con_act")
if nActo > 0 .and. nActo <= len(::aActo)
:conactividad := val(::aActo[nActo])
endif
//---------------------------------------------------------- -------------
:FastUpdate()
aadd(aDatosArray,{:id,:connumero,:conHistoria,:confecha,:con ho1,:conho2})
::oDbfOri:Skip()
enddo
::oSqlDes:Update()
//----------- Actualizacion de cip y numero de historia
WaitOn("Actualizando contactos","Un momento...")
AppData:oSqlSource:Execute("UPDATE IGNORE contactos SET conhistoria
= (SELECT historiapac FROM pacientes WHERE codigopac = connumero ) WHERE
id > 0 ")
WaitOff()
End with
Un saludo y Gracias .
Juan José García .
BISOFT