martes, 15 de enero de 2008

Jaybird Problemas ?

5 de Diciembre 2007

He desarrollado ya varias entradas de datos y la verdad con los objetos de acceso a datos que desarrolle las cosas ya son mas aceptables y puedo desarrollar bastante rápido esto me esta gustando.
Toda estaba bien hasta que me percato de algo extraño cuando procedía a grabar datos en una tabla con llave primaria compuesta se modificaban todos los registros para los cuales coincidía el ultimo campo de la llave compuesta me explico mejor con un ejemplo:

TABLA=DEMO1
sistema codigo campo valor
002 1 UNO 100
002 2 DOS 200
002 3 TRES 5000
002 5 UNO 300
002 10 DOS 100
002 20 UNO 200

PRIMARY KEY = CAMPO+CODIGO+SISTEMA

Si yo actualizo el campo valor de 200 a 10 para los registros con el campo sistema='002' y ademas con el campo codigo='20' esto deberia afectar solo a un registro.

Después de realizar la actualización el resultado debería ser este:

sistema codigo campo valor
002 20 UNO 200

Pero los resultados fueron diferentes obteniendo los siguientes datos:

sistema codigo campo valor
002 1 UNO 10 (*)
002 2 DOS 200
002 3 TRES 5000
002 5 UNO 10 (*)
002 10 DOS 100
002 20 UNO 10 (*)

Esto para mi es un Horror, bueno pensé algo estoy haciendo mal así que a revisar todo el código que he avanzado para detectar el posible error ese día me amanecí para variar (jajaa casi siempre lo ago) . Analizando todo llegue a la conclusión siguiente el controlador Jaybird tiene un problema muy pero muy grande como antes no se percataron de eso realmente es algo terrible.

Decidí escribirle a Roman Rowinsky el creador de Jaybir para que me oriente que cosa estava haciendo mal. Roman Rowinsky me contesto lo siguiente:

Please post this email into our bug tracker at
http://tracker.firebirdsql.org

It looks like a bug in JDBC driver when handling the compound primary keys.

Aqui me esta confirmando que efectivamente existe un problema con el controlador JDBC de Jaybird en la actualización de registro con tablas que tienen Llaves primarias compuestas.
Bueno esto me puso muy preocupado, publique el bug en la dirección que Roman me indico y en esa dirección me percate que existen Bugs desde el 2006 que no se solucionan hasta la fecha o si se solucionaron no se menciona nada de ello.

Al percatarme de ello estaba al borde de a locura y que hago me dije lo primero tranquilizarme y pensar friamente que seria los mas adecuado hacer, entonces se me ocurrieron las siguientes alternativas:
  • Cambiarme de Motor de Base de datos
  • Pedirle Porfavor a Roman que me Ayudase con el problema
  • Yo mismo corregir el controlador
Asi que empece a analizar las diferentes alternativas que tenia, la primera cambiarme de base de datos bien a Postgress o Mysql me decidí por Mysql así que estuve explorando las posibilidades con esta base de datos, como se sabe Mysql apartir de la versión 5.0 comienza a dar soporte a Procedimientos almacenados,disparadores , funciones definidas por el usuario, etc. estuve revisando el lenguaje de programación que utiliza Mysql y toda la información que encontré me llevo a pensar que Mysql todavía no esta muy maduro en estos temas como RBDMS, mi conocimiento con Firebird data desde el 2004 y con el cual he desarrollado muchos sistemas, esto me garantizaría tiempo y funcionalidad para la generación de cualquier tipo de reporte por mas complejo que este fuese, con IBSQL (Lenguaje de Firebird) todo lo podría resolver. Así que me propuse Corregir el Controlador yo mismo si en 24 horas no lo podía corregir el cambio de motor de base de datos era inevitable.

Le pedí a Roman que me diga donde podía conseguir el código fuente de Jaybird 2.1.1 (Es la versión que estoy usando) pq' en la pagina de descarga solo se encuentra los fuentes de Jaybird 2.1 Roman me contesto lo siguiente:

You have to check out the sources from the CVS

cvs -d :pserver:anonymous@firebird.cvs.sourceforge.net:/cvsroot/firebird
co -R Jaybird_2_1_1 client-java

Aca entra el excelente soporte que tiene Netbeans 6.0 para el trabajo con CVS es de lo mejor que yo he visto.
Una ves trabajando con los fuentes de Jaybird detecte el problema en la clase FBRowUpdater realice la corrección de manera exitosa compilando nuevamente Jaybird con la versión parchada dando resultados satisfactorios, sinceramente que al ver que la nueva versión compilada de Jaybird funcionaba correctamente, la tranquilidad regreso a mi. Corregir el controlador no fue tarea fácil lo primero, hay que aceptar el reto y tener la seguridad de que todo se puede solo el factor tiempo era mi enemigo. Con este problema superado y habiendo ganado mucho mas experiencia en Java con 1 mes de estar desarrollando en este lenguaje, en ese momento me sentí muy contento y con la confianza de que ningún problema me detendría para desarrollar este sistema.

Le escribí a Roman un correo con el código corregido:

Te agradesco por el apoyo y los fuentes de Jaybird. te envio la correccion que he realizado.
saludosy y Nuevamente Gracias.

Atte.
Oscar Zelada Pozo

//***********************************************************************************************
private int[] getParameterMask() throws SQLException {

// loop through the "best row identifiers" and set appropriate falgs.
FBDatabaseMetaData metaData = new FBDatabaseMetaData(gdsHelper);

ResultSet bestRowIdentifier = metaData.getBestRowIdentifier(
"", "", tableName, DatabaseMetaData.bestRowSession , true);
try {
int[] result = new int[xsqlvars.length];
boolean hasParams = false;
while(bestRowIdentifier.next()) {
String columnName = bestRowIdentifier.getString (2);
if (columnName == null)
continue;

boolean found = false;
for (int i = 0; i <>) && "DB_KEY".equals(xsqlvars[i].sqlname)) {
result[i] = PARAMETER_DBKEY;
found = true;
break;
} else
if (columnName.equals(xsqlvars[i].sqlname)) {
result[i] = PARAMETER_USED;
found = true;
break;
}
//---------Este Else--No es necesario Pq' los elementos del Array se inicializan en cero-----
//---------Como el for siempre recorre todos los parametros de Xsqlvars siempre setea todos los anteriores a cero-----
//----------y si ya se asigno un valor diferente a cero sera chancado por eso esas lineas estan de mas---------
//---------el error era que siempre queda el ultimo campo de la llave primaria y sera el unico------
//--------Que se tomara en consideracion para el where del Update------------------------------------
//--------------Gracias por Todo Roman Saludos desde Peru Atte. Oscar Zelada--------------------
// else
// result[i] = PARAMETER_UNUSED;
}

// if we did not found a column from the best row identifier
// in our result set, throw an exception, since we cannot
// reliably identify the row.
if (!found)
throw new FBResultSetNotUpdatableException(
"Underlying result set does not contain all columns " +
"that form 'best row identifier'.");
else
hasParams = true;
}

if (!hasParams)
throw new FBResultSetNotUpdatableException(
"No columns that can be used in WHERE clause could be " +
"found.");

return result;
} finally {
bestRowIdentifier.close();
}
}


Aqui pongo los binarios de Jaybird 2.1.1 que corrige el problema de llave primaria compuesta por si alguien los necesita.

2 comentarios:

Anónimo dijo...

LA VOLUNTAD Y EL CONOCIMIENTO SON HERMANOS Q SI VAN JUNTOS SON IMPARABLES NO DESMAYES NUNCA SUERTE EN TODO

EROSG

Anónimo dijo...

Hola Oscar,veo ke has trabajado con FoxPro y Power,haber si me puedes ayudar.He desarrollado un Sistema con Power 9.0 pero con tablas DBF (por rekerimientos de la empresa).La verdad es ke no tengo mucha experiencia con DBF's y Fox pero si con Power.He creado las tablas y como llaves primaria he usado indices.Sin embargo noto ke las consultas o la coneccion a la BD es DEMASIADO lenta.Uso Driver do Microsoft dBase (*.dbf).Probe cambiando de driver al MS FoxPro pero tendria ke cambiar toda la syntaxis de los dw ya ke hay error al parecer. Te agradesco de antemano tu ayuda..