Posible bug en la versión del driver JDBC en uso

Inicio Foros Foro principal Desarrolladores Posible bug en la versión del driver JDBC en uso

Viendo 4 entradas - de la 1 a la 4 (de un total de 4)
  • Autor
    Entradas
  • #31387
    Javier Ader
    Participante

    Buenas. Alguien puede chequear si el siguiente test les tira el mismo error que a mi:


    package org.openXpertya.util;

    public class TestBugSetIntJDBCDriver {

    /**
    * @param args
    */
    public static void main(String[] args) {
    org.openXpertya.OpenXpertya.startupEnvironment( true );
    int idOrg = 0;
    int idInvoice = 0;
    int i = 5;
    while (i-- >0)
    {
    //tira error
    int bPartnerId = DB.getSQLValue(null,
    "SELECT C_BPartner_ID FROM C_BPartner WHERE AD_OrgBP_ID=?",
    idOrg);
    //NO tira error!???? wtf
    int stdPrec = DB.getSQLValue(null,
    "SELECT c.StdPrecision FROM "+
    "C_Currency c INNER JOIN "+
    "C_Invoice x ON (x.C_Currency_ID=c.C_Currency_ID) WHERE x.C_Invoice_ID=?",
    idInvoice);

    }

    }

    }

    El primer DB.getSQLValue tira el sig error

    ===========> DB.getSQLValue: SELECT C_BPartner_ID FROM C_BPartner WHERE AD_OrgBP_ID=? - Param1=0 [null]
    org.postgresql.util.PSQLException: No se ha especificado un valor para el parámetro 1.; State=22023; ErrorCode=0
    at org.postgresql.core.v3.SimpleParameterList.checkAllParametersSet(SimpleParameterList.java:134)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:179)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:437)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:353)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:257)
    at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.postgresql.ds.common.PooledConnectionImpl$StatementHandler.invoke(PooledConnectionImpl.java:467)
    at $Proxy1.executeQuery(Unknown Source)
    at org.openXpertya.util.CPreparedStatement.executeQuery(CPreparedStatement.java:187)
    at org.openXpertya.util.DB.getSQLValue(DB.java:1211)
    at org.openXpertya.util.TestBugSetIntJDBCDriver.main(TestBugSetIntJDBCDriver.java:16)

    PERO EL SEGUNDO NO!!!!!
    Estoy debugeando el código a nivel del driver (las fuentes de la versión que se esta usando actualmente las postie en este otro thread https://www.libertya.org/comunidad/foro-libertya/8-desarrolladores/1454#1454 por si alguien quiere mirar exactamente en donde se tira la excepción ). El tema es que hice otras modificaciones a nivel de conexiones y no estoy corriendo el fuentes originales, así que tal vez me ocurra solo a mi… pero igual me resulta terriblemente raro que una query tire sistemáticamente error y la otra no (dicho sea de paso, las dos son queries reales usadas actualmente dentro de libertya; en particular la primera se usa al completar una factura; y la segunda al guardar una linea de una factura).

    Después veo en el changelog del driver si hay algún fix con respecto a este tema y/o envió un email a la lista de desarrolladores del driver. Realemnte no se por donde viene… me da la sensación que hay un SimpleParameterList.clear() [el metodo checkAllParametersSet por alguna razón es llamado dos veces al momento de hacer un executeQuery; la primera vez no tira error… la segunda si….)en el medio PERO esto solo ocurre en la primer sentencia…

    PD : si es un error, es entendible que no haya pasado bastante inadvertido; la sentencia del error se dispara una sola vez por logueo cada vez que se completa una factura de proveedor (supongo que de cliente también); después todos los valores son cacheados (erroneamente ya que al haber una execpción DB retorna -1 y el valor obtenido defaultea a 0 en MOrg.getLinkedC_BPartner_ID() y se cachea)

    #34434
    Javier Ader
    Participante

    Bueno, editenme el título si pueden porque el error no esta en el driver si no en Libertya (lo que me confudió es que CPreparedStatement.executeQuery() al fallar el primer intento por un error semántico de la query, lo reintenta, y antes de hacer esto clarea los parámetros y por lo tanto al reejecutarlo tira el error que puse antes; esto se da en la parte que dice Try Locally; dicho sea de paso es bastante dudoso que este código sea correcto…).
    La sentencia “SELECT C_BPartner_ID FROM C_BPartner WHERE AD_OrgBP_ID=? ” falla en el primer intento porque se setea el parámetro como int (PreparedStatement.setInt(int)), esto termina en un error en Postgres porque la columan AD_OrgBP_IP es de tipo character varying (no me pregunten por que…) y Postgres (al menos la versión que esta usando libertya 10.3) OBLIGA a un casting explicito entre int y character varying cuando el operador es “=” (dicho de otra manera; no tiene casting implícito entre estos dos tipos de datos). Probablemente bajo otros SMDB como Oracle esto este permitido.
    Hay que remarcar que todo el código que vi que trata con este columna en particular de la tabla CBPartner asume que este columna es int y a veces string ….(a nivel de metadatos, la columna es de tipo Boton, asi que esto no trae problemas en este punto). Estos puntos si no me faltan algunos (es probable) son
    MOrg.getLinkedC_BPartner_ID(): de donde viene el error que se muestra al completar una factura (pero que la factura en si misma se completa sin error)
    BPartnerOrgLink.doIt(): ya que en este caso se llama a MBPartner.setAD_OrgBP_ID(int); pero en este caso el metodo es definido en MBPartner y no heredado de la clase generada automáticamente (ahí si correctamente, el tipo de esta columna es string)
    BPartnerOrgUnLink.doIt(): usa un “mezcla” …. por un lado usa el getter de tipo int definido en MBPartner; pero al momento se “deslinkear” la entidad a una organización , usa el seter definido en X_C_BPartner (en realidad lo hace Java por sobrecarga de métodos; al ser llamado setAD_OrgBP_ID con parametro null el cual va a parar al seter dado en X_C_BPartner ya que este tiene parámetro string…)

    En los dos ultimos casos, la cosa creo que funciona; mal o bien, siempre se castea entre strigs e ints previo a las modificaciones en la base de datos (incluso si no se hiciese la conversión creo que funcionaria de todas maneras ya que los updates en PO no se hacen usando parametros de un prepared statement… creo…). Ahora, en el caso MOrg.getLinkedC_BPartner_ID() se falla….

    No se cual será la solución correcta; si redefiniar la columna en base de datos a int y dejar de hacer la conversion de int a string en MBParnter (y que los dos procesos se modifiquen acordermente) o modificar MOrg.getLinkedC_BPartner_ID() para que no use un parámetro de tipo int si no de tipo string…
    Si se optase por lo último MOrg.getLinkedC_BPartner_ID() podría quedar asi:

    Code:
    public int getLinkedC_BPartner_ID() {
    //TEST: Comentar el siguinte if y la llave que cierra para que MOrg
    // NO chacuie la entidad linkeada
    if (m_linkedBPartner == null) {
    //bug: se debe convertir getAD_Org_ID a string Y NO llamar directamente con
    //el int. La columna AD_OrgBP_ID es de tipo character varying NO int
    int C_BPartner_ID = DB.getSQLValue(null,
    “SELECT C_BPartner_ID FROM C_BPartner WHERE AD_OrgBP_ID=?”,
    Integer.toString(getAD_Org_ID()) );

    if (C_BPartner_ID < 0) { // not found = -1 C_BPartner_ID = 0; } m_linkedBPartner = new Integer(C_BPartner_ID); } return m_linkedBPartner.intValue(); }

    Lo testie y anda (la clave está en Integer.toString(getAD_Org_ID()) ). De paso, como está puesto en el primer comentario del código, no se si es muy correcto que se cachee la entidad asociada a un organización por obvias razones (si desde otro cliente se “deslinkea” o se “linkea” el cliente actual sigue viendo las cosas como antes…)

    PD : gravedad del bug? ni idea, pero me parece que para el uso común no tiene grandes implicaciones (la entidad linkeada a una organización se usa para generar automáticamente “contra documentos”… un concepto para mi gusto muuuy esotérico jajaja y la verdad que no se si se usa en muchas instalaciones)

    #34436
    Federico Cristina
    Superadministrador

    Acabo de ejecutar el código y no me presenta error alguno en consola, y obtengo -1 en cada caso, lo cual es correcto para los parametros dados… seguramente debido a que estoy testeando en postgre 8.2, lo cual cambia para 8.3 y ahí sí seguramente se presente el error debido a la necesidad de casting explícito…

    Por qué es un character varying AD_OrgBP_ID? Muy probablemente se deba a un error cuando se creo la columna (fijate la fecha de creación de la misma: Febrero de 2004!).

    Saludos,
    Federico

    #34435
    Javier Ader
    Participante

    Puede ser pero tené en cuenta que el error (algo que no puse….) se muestra a nivel “fine” y que el error de la “falta de parametros” a nivel severe (este ultimo puede no estarte ocurriendo por otras razones; tal vez tu “try locally” en exeuteQuery() tiene éxito); y en los dos casos, con o sin error DB devuelve -1 (que como decís es correcto justo en el ejemplo, pero podría no serlo).
    Si no me equivoco para que se muestren todos estos mensajes por consola habría que agregar un linea CLogMgt.setLevel(Level.ALL); al test justo debajo del org.openXpertya.OpenXpertya.startupEnvironment( true );
    (yo la excepción la vi solo después de poner un breakpoint en el primer catch de CPreparedStatement.excecuteQuery())
    Otra forma de verificar si Postgres 8.2 soporta este casting explicito sería directamente ejecutar desde pgAdmin o algún cliente consola la sentencia:
    “SELECT C_BPartner_ID FROM Libertya.C_BPartner WHERE AD_OrgBP_ID=0”
    Esa sentencia desde mi pgAmidn contra el server 8.3 me tira el mismo error semántico de castings que la excepción que en CPreparedStatement.

Viendo 4 entradas - de la 1 a la 4 (de un total de 4)
  • Debes estar registrado para responder a este debate.